home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d4 / Telnet2.6.1d4.src.sit.hqx / Telnet 2.6.1d4 source / source / vs / rsmac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-18  |  75.3 KB  |  2,710 lines

  1. #define NCSA_TELNET
  2. /*
  3.  *
  4.  *      Virtual Screen Kernel Macintosh Real Screen Interface
  5.  *                          (rsmac.c)
  6.  *
  7.  *   National Center for Supercomputing Applications
  8.  *      by Gaige B. Paulsen
  9.  *
  10.  *    This file contains the macintosh real screen calls for the NCSA
  11.  *  Virtual Screen Kernel.
  12.  *
  13.  *      RSbell(w)                   - Ring window w's bell
  14.  *      RScursoff(w)                - Turn the cursor off in w
  15.  *      RScurson(w,x,y)             - Turn the cursor on in w at x,y
  16.  *      RSdraw(w,x,y,a,len,ptr)     - Draw @x,y in w string@ptr for length len
  17.  *      RSdelchars(w,x,y,n)         - Delete n chars in w from x,y
  18.  *      RSdellines(w,t,b,n)         - Delete n lines in region t->b in w
  19.  *      RSerase(w,x1,y1,x2,y2)      - Erase from x1,y1 to x2,y2 in w
  20.  *      RSinitall()                 - Initialize the world if necessary
  21.  *      RSinslines(w,t,b,n)         - Insert n lines in region t->b in w
  22.  *      RSinsstring(w,x,y,a,len,ptr)- Insert len chars @x,y in w attrib a
  23.  *      RSsendstring(w,ptr,len)     - Send string @ptr length len from window w
  24.  *        RSbufinfo( w, total,current)- Tells you the total/current lines in buffer
  25.  *        RSdrawsep( w, y1,draw)        - Tells you to draw the line at y1 (0 is erase)
  26.  *        RSmargininfo( w, total, current)    - Tells you total/current columns in VS
  27.  *
  28.  *
  29.  *  Macintosh only Routines:
  30.  *    NI    RSregnconv( *)                - Convert region to rect coords
  31.  *  NI  RSsetwind(w)                - Set the port and vars to window w
  32.  *  NI  RSsetattr(a)                - Set font/text style to a
  33.  *    NI    RSsetConst(w)
  34.  *    ML    RSattach(w,wind)            - Attach the RS (w) to window wind
  35.  *    ML    RSdetach(w)                - Ready window for go-away
  36.  *    ML    RSselect(w,pt,shift)        - Handle selection RS (w) point (pt) and (shift) if held down
  37.  *    ML    RSzoom(window,code,shifted)    - Zoom Box handling
  38.  *    ML    RSsize( window, where)        - Resize handling
  39.  *    IN    RSgetwindow(w)                - Get the WindowPtr for RS (w)
  40.  *    IN    RSfindvwind(wind)            - Find the (RS/VS) # of wind
  41.  *    IN    RSfindscroll( control, n)    - Find which VS the control is in and which control it is
  42.  *      RSupdate(wind)                - Handle updates on WIND, return 0 if not an RS
  43.  *        RSactivate(w)                - Handle activate events 
  44.  *        RSdeactivate(w)                - Handle deactivate events 
  45.  *        RSGetTextSel(w,table)        - Returns handle to text selection of window w, table->tabs
  46.  *        RSchangefont(w,fnum,fsiz,r)    - Set (w) to font fnum, size fsiz, resize window if (r)
  47.  *        RSgetfont(w, &fnum, &fsiz)    - Get the font size and number into fnum and fsiz
  48.  *        RSnewwindow( wDims, sb, wid, lines
  49.  *            name,wrap,fnum,fsiz,
  50.  *            showit, goaway)            - Returns VS # of newly created text window -
  51.  *                                      wDims (dimension),sb(scrollback),wid(width 80/132),
  52.  *                                    lines (# of lines, 24 <> 66),
  53.  *                                      name(window), wrap(0/1),fnum,fsiz, showit(vis),goaway(0,1)
  54.  *        RSkillwindow( w)            - Destroys, deallocates, kills window (w)
  55.  *        RSclick(window, eventRecord)- Handle clicks in window (returns false if not RS window)
  56.  *        RShide(w)                    - Hide RS (w)
  57.  *        RSshow(w)                    - Show RS (w)
  58.  *        RScprompt(w, FilterProc)    - Prompt for colors...FilterProc is for Modal Dialog
  59.  *        RSsetcolor(w,n,r,g,b)        - Set one of the 4 colors of RS (w) to R,G,B
  60.  *        RSgetcolor(w,n,r,g,b)        - Get one of the 4 colors of RS (w) into R,G,B
  61.  *        RSmouseintext(w,myPoint)    - Returns true if Mouse is in text part of current RS window
  62.  *        RSskip(w,on)                - Activate/deactivate drawing in an RS
  63.  *        
  64.  *        IN - Informational
  65.  *        ML - Mid Level
  66.  *        NI - Necessary Internal
  67.  *           - Suggested calls
  68.  *
  69.  *      Version Date    Notes
  70.  *      ------- ------  ---------------------------------------------------
  71.  *      0.01    861102  Initial coding -GBP
  72.  *      0.25    861106  Added code from screen.c -GBP
  73.  *      0.50    861113  First compiled edition -GBP
  74.  *        2.1        871130    NCSA Telnet 2.1 -GBP
  75.  *        2.2     880715    NCSA Telnet 2.2 -GBP
  76.  *        2.6        7/92    put globals into struct, cursors into array, and cleaned up 
  77.  *                        some of the font typedefs            Scott Bulmahn
  78.  *        2.6b4    12/92    Cleaned up the code, and added double clicking -- Scott Bulmahn
  79.  *
  80.  */
  81.  
  82. #ifdef MPW
  83. #pragma segment RS
  84. #endif
  85.  
  86. #define __ALLNU__
  87. #include <OSUtils.h>
  88. #include <Palettes.h>
  89. #include <Picker.h>        /* BYU LSC */
  90. #include <Fonts.h>
  91. #include <stdio.h>
  92. #include <string.h>
  93. #include <ctype.h>
  94.  
  95. #include "TelnetHeader.h"
  96. #include "DlogUtils.proto.h"
  97. #include "configure.proto.h"    // For colorboxmodalproc and colorboxproc
  98. #include "maclook.proto.h"
  99. #include "network.proto.h"
  100. #include "menuseg.proto.h"
  101. #include "vskeys.h"
  102. #include "vsdata.h"
  103. #include "vsinterf.proto.h"
  104. #include "vsintern.proto.h"
  105. #include "telneterrors.h"
  106. #include "wind.h"
  107. #include "rsdefs.h"
  108. #include "parse.proto.h"        // For SendNAWSinfo proto
  109. #include "wdefpatch.proto.h"    /* 931112, ragge, NADA, KTH */
  110. #include "url.proto.h"
  111. #include "drag.proto.h"
  112.  
  113. #define NFDEF {0,0,0}
  114. #define NBDEF {65535,65535,65535}
  115. #define BFDEF {0,61183,11060}
  116. #define BBDEF {61183,2079,4938}
  117. #define UFDEF {1,0,0}
  118. #define UBDEF {0,0,0}
  119.  
  120. static    void HandleDoubleClick(short w, short modifiers);
  121.  
  122. #define    MYSETRECT(a,b,c,d,e)    a.left = b; \
  123.                                 a.top = c;\
  124.                                 a.right = d;\
  125.                                 a.bottom = e;\
  126.                                 
  127. #define INFINITY    20000        // Will screens ever be this large?
  128.  
  129. #ifdef NCSA_TELNET
  130. extern WindRec *screens;
  131. #endif NCSA_TELNET
  132. extern SysEnvRec    theWorld;
  133.  
  134. #include "rsmac.proto.h"
  135.  
  136. void RScheckmaxwind(Rect *,short , 
  137.             short , short *, short *);
  138.  
  139. void RScalcwsize(short w, short width);
  140.  
  141. short MaxRS;
  142.  
  143. RSdata *RSlocal, *RScurrent;
  144. Rect    noConst,
  145.         RScur;                /* cursor rectangle */
  146.  
  147. RgnHandle RSuRgn;            /* update region */
  148.  
  149. short RSw=-1,         /* last window used */
  150.     RSa=0;          /* last attrib used */
  151. short RScolor=1;        /* true if try to use color stuff */
  152.  
  153. short RScolors[]=
  154.     { 33,            /* black */
  155.       30,            /* white */
  156.       205,            /* red */
  157.       341,            /* green */
  158.       409,            /* blue */
  159.       273,            /* cyan */
  160.       137,            /* magenta */
  161.       69            /* yellow */
  162.       };
  163.  
  164. void    RSunload(void) {}
  165.  
  166. void RSinitall
  167.   (
  168.     short max /* max nr windows to allow */
  169.   )
  170.   /* initializes handling of terminal windows. */
  171.   {
  172.     short i;
  173.     extern SysEnvRec theWorld;
  174.  
  175.     MaxRS = max;
  176.     RSlocal = (RSdata *) NewPtrClear(MaxRS * sizeof(RSdata));
  177.     for (i = 0; i < MaxRS; RSlocal[i++].window = 0L)
  178.       {
  179.         RScurrent = RSlocal + i;
  180.         RScurrent->id = 'RSDA';
  181.         RScurrent->color[0] = 0;            /* Foreground */
  182.         RScurrent->color[1] = 1;            /* Background */
  183.         RScurrent->color[2] = 2;            /* Blink Fore */
  184.         RScurrent->color[3] = 3;            /* Blink Back */
  185.         RScurrent->cursor.top = 0;
  186.         RScurrent->cursor.bottom = 0;
  187.         RScurrent->cursor.left = 0;
  188.         RScurrent->cursor.right = 0;
  189.       }
  190.     RSuRgn = NewRgn();
  191.     RScur.left = 0;
  192.     RScur.top = 0;
  193.     RScur.bottom = 0;
  194.     RScur.right = 0;
  195.     RScolor = theWorld.hasColorQD;
  196.   } /* RSinitall */
  197.  
  198. short RSTextSelected(short w) {        /* BYU 2.4.11 */
  199.   return(RSlocal[w].selected);    /* BYU 2.4.11 */
  200. }                                /* BYU 2.4.11 */
  201.  
  202. void RSsetConst
  203.   (
  204.     short w
  205.   )
  206.   /* sets "noConst" global to a zero-based rectangle equal in size
  207.     to the specified terminal window. */
  208.   {
  209.   noConst.left = 0;
  210.   noConst.top = 0;
  211.   noConst.right = RSlocal[w].width;
  212.   noConst.bottom = RSlocal[w].height;
  213.   } /* RSsetConst */
  214.  
  215. /****************************************************************************/
  216. /*  Given a window record number, do a SetPort() to the window associated with
  217. *   that window record.
  218. */
  219. short RSsetwind
  220.   (
  221.     short w
  222.   )
  223.   {
  224.     if ((w < 0) || (w > MaxRS))
  225.         return(-3);
  226.     if (RSw != w)                                /* if last window used is different */
  227.       {
  228.         if (RSlocal[w].window == 0L)
  229.             return(-4);
  230.         RScurrent = RSlocal + w;
  231.         RSw = w;
  232.         RSa = -1; /* attributes will need setting */
  233.         SetPort(RScurrent->window);
  234.         return(1);
  235.       }
  236.     SetPort(RScurrent->window);
  237.     return(0);
  238.   } /* RSsetwind */
  239.  
  240. void RSbell
  241.   (
  242.     short w
  243.   )
  244.   /* gives an audible signal associated with the specified window. */
  245.   {
  246.     RSsetwind(w);
  247.     if (FrontWindow() != RScurrent->window)
  248.       {
  249.       /* beep and temporarily invert the window contents, so
  250.         the user sees which window is beeping */
  251.         InvertRect(&RScurrent->window->portRect);
  252.         SysBeep(8);
  253.         InvertRect(&RScurrent->window->portRect);
  254.       }
  255.     else
  256.       /* window is frontmost--just beep */
  257.         SysBeep(8);
  258.   } /* RSbell */
  259.  
  260. void    RScursblink( short w)        /* Blinks the cursor */
  261. {
  262.     GrafPtr    oldwindow;
  263.     long    now = TickCount();
  264.     
  265.     if (now > TelInfo->blinktime) {
  266.         if (VSvalids(w) != 0)            /* BYU 2.4.12 */
  267.             return;                        /* BYU 2.4.12 */
  268.         if (!VSIcursorvisible())        /* BYU 2.4.12 */
  269.             return;                        /* BYU 2.4.12 - cursor isn't visible */
  270.     
  271.         GetPort(&oldwindow);            /* BYU 2.4.11 */
  272.         TelInfo->blinktime = now + 40;            /* BYU 2.4.11 */
  273.         RSlocal[w].cursorstate ^= 1;     /* BYU 2.4.11 */
  274.         SetPort(RSlocal[w].window);        /* BYU 2.4.11 */
  275.         InvertRect(&RSlocal[w].cursor);    /* BYU 2.4.11 */
  276.         SetPort(oldwindow);                /* BYU 2.4.11 */
  277.     }
  278. } /* RScursblink */
  279.  
  280. void RScursblinkon                        /* BYU 2.4.18 */
  281.   (                                        /* BYU 2.4.18 */
  282.     short w                                /* BYU 2.4.18 */
  283.   )                                        /* BYU 2.4.18 */
  284.   /* Blinks the cursor */                /* BYU 2.4.18 */
  285.   {                                        /* BYU 2.4.18 */
  286.       if (!RSlocal[w].cursorstate) {        /* BYU 2.4.18 */
  287.         GrafPtr oldwindow;                /* BYU 2.4.18 */
  288.         GetPort(&oldwindow);            /* BYU 2.4.18 */
  289.         RSlocal[w].cursorstate = 1;     /* BYU 2.4.18 */
  290.         SetPort(RSlocal[w].window);        /* BYU 2.4.18 */
  291.         InvertRect(&RSlocal[w].cursor);    /* BYU 2.4.18 */
  292.         SetPort(oldwindow);                /* BYU 2.4.18 */
  293.     }                                    /* BYU 2.4.18 */
  294.   } /* RScursblink */                    /* BYU 2.4.18 */
  295.  
  296. void RScursblinkoff                        /* BYU 2.4.11 */
  297.   (                                        /* BYU 2.4.11 */
  298.     short w                                /* BYU 2.4.11 */
  299.   )                                        /* BYU 2.4.11 */
  300.   /* Blinks the cursor */                /* BYU 2.4.11 */
  301.   {                                        /* BYU 2.4.11 */
  302.       if (RSlocal[w].cursorstate) {        /* BYU 2.4.11 */
  303.         GrafPtr oldwindow;                /* BYU 2.4.11 */
  304.         GetPort(&oldwindow);            /* BYU 2.4.11 */
  305.         RSlocal[w].cursorstate = 0;     /* BYU 2.4.11 */
  306.         SetPort(RSlocal[w].window);        /* BYU 2.4.11 */
  307.         InvertRect(&RSlocal[w].cursor);    /* BYU 2.4.11 */
  308.         SetPort(oldwindow);                /* BYU 2.4.11 */
  309.     }                                    /* BYU 2.4.11 */
  310.   } /* RScursblink */                    /* BYU 2.4.11 */
  311.  
  312. void RScursoff
  313.   (
  314.     short w
  315.   )
  316.   /* hides the text cursor for the specified window. Assumes it
  317.     is currently being shown. */
  318.   {
  319.     if (RSlocal[w].skip || !RSlocal[w].cursorstate)        /* BYU 2.4.11 */
  320.         return;
  321.     RSsetwind(w);
  322.     RScurrent->cursorstate = 0;                            /* BYU 2.4.11 */
  323.     InvertRect(&RScurrent->cursor);
  324.   } /* RScursoff */
  325.  
  326. void RScurson
  327.   (
  328.     short w,
  329.     short x,
  330.     short y
  331.   )
  332.   /* displays the text cursor for the specified window, at the
  333.     specified position. Assumes it isn't currently being shown. */
  334.   {
  335.     if (RSlocal[w].skip || RSlocal[w].cursorstate)        /* BYU 2.4.11 */
  336.         return;
  337.     RSsetwind(w);
  338.  
  339.     RScurrent->cursor.left = x * RScurrent->fwidth;            /* BYU 2.4.11 */
  340.     RScurrent->cursor.top  = y * RScurrent->fheight;        /* BYU 2.4.11 */
  341.  
  342.     switch (gApplicationPrefs->CursorType) {                                            /* BYU 2.4.11 */
  343.         case UNDERSCORECURSOR:                                        /* BYU 2.4.11 */
  344.             RScurrent->cursor.top  += RScurrent->fheight;            /* BYU 2.4.11 */
  345.             RScurrent->cursor.right  = RScurrent->cursor.left + RScurrent->fwidth;    /* BYU 2.4.11 */
  346.             RScurrent->cursor.bottom = RScurrent->cursor.top + 1;    /* BYU 2.4.11 */
  347.             break;
  348.         case VERTICALCURSOR:                                        /* BYU 2.4.11 */
  349.             RScurrent->cursor.left += 2;                            /* BYU 2.4.11 */
  350.             RScurrent->cursor.right  = RScurrent->cursor.left + 1;    /* BYU 2.4.11 */
  351.             RScurrent->cursor.bottom = RScurrent->cursor.top + RScurrent->fheight;    /* BYU 2.4.11 */
  352.             break;
  353.         case BLOCKCURSOR:                                            /* BYU 2.4.11 */
  354.         default:                                                    /* BYU 2.4.11 */
  355.             RScurrent->cursor.right  = RScurrent->cursor.left + RScurrent->fwidth;    /* BYU 2.4.11 */
  356.             RScurrent->cursor.bottom = RScurrent->cursor.top + RScurrent->fheight;    /* BYU 2.4.11 */
  357.             break;
  358.     }
  359.  
  360.     if (!gApplicationPrefs->BlinkCursor) {                                    /* BYU 2.4.11 */
  361.         RScurrent->cursorstate = 1;                        /* BYU 2.4.11 */
  362.         InvertRect(&RScurrent->cursor);                    /* BYU 2.4.11 */
  363.     }                                                    /* BYU 2.4.11 */
  364.   } /* RScurson */
  365.  
  366. void RSTextFont(short myfnum, short myfsiz, short myface)                 /* BYU */
  367. {                                        /* BYU */
  368.     if ((myfnum == monaco) &&             /* BYU - If Monaco, size 9, and bold, then */
  369.         (myfsiz == 9) &&                /* BYU */
  370.         (myface & bold))    {            /* BYU */
  371.         TextFont(75);                    /* BYU - use NCSA's Monaco. */
  372.     } else {                            /* BYU */
  373.         TextFont(myfnum);                /* BYU */
  374.     }                                    /* BYU */
  375. }                                        /* BYU */
  376.  
  377. /* sets the text attributes for drawing into the current window. */
  378. void RSsetattr(short a)
  379. {
  380.    if (VSisgrph(a))
  381.         TextFont(74); /* use "NCSA VT" font for special graphics */
  382.     else
  383. #if 1                                                    /* BYU */
  384.         RSTextFont(RScurrent->fnum,RScurrent->fsiz,a);     /* BYU - use user-selected text font */
  385. #else
  386.         TextFont(RScurrent->fnum); /* use user-selected text font */
  387. #endif
  388.  
  389.     TextSize(RScurrent->fsiz);
  390.  
  391. /* BYU - bold system fonts don't work (they overwrite the scroll bars), 
  392.          but NCSA's 9 point Monaco bold works okay. */
  393.  
  394.     TextFace((a & outline) >> 1);     /* BYU - do outline as underline setting */
  395.  
  396. #ifdef GOTTHEGOUGH
  397.     if (a & bold)                                    /* NCSA: SB */
  398.         TextFace(thePort->txFace + bold);            /* NCSA: SB */
  399. #endif
  400.  
  401.   /* set up reverse video setting */
  402.     if (RScolor)
  403.       {
  404.         if (VSisrev(a))
  405.             TextMode(notSrcCopy);
  406.         else
  407.             TextMode(srcCopy);
  408.       }
  409.     else
  410.       {
  411.         if (VSisrev(a))
  412.           {
  413.             BackPat(PATTERN(qd.black));    /* Reverses current attributes regard */
  414.             PenPat(PATTERN(qd.white));    /* less of the color, etc.... */
  415.           }
  416.         else
  417.           {
  418.             BackPat(PATTERN(qd.white));
  419.             PenPat(PATTERN(qd.black));
  420.           } /* if */
  421.       } /* if */
  422.   /* use colors to stand in for blink setting */
  423.     if (VSisblnk(a))
  424.       {
  425.         if (RScolor)
  426.           {
  427.             PmForeColor(2);
  428.             PmBackColor(3);
  429.           }
  430.         else
  431.           {
  432.             ForeColor((long) RScolors[RScurrent->color[2]]);    /* Blink foreground */
  433.             BackColor((long) RScolors[RScurrent->color[3]]);    /* Blink Background */
  434.           } /* if */
  435.       }
  436.     else
  437.       {
  438.         if (RScolor)
  439.           {
  440.             PmForeColor(0);
  441.             PmBackColor(1);
  442.           }
  443.         else
  444.           {
  445.             ForeColor((long) RScolors[RScurrent->color[0]]);    /* normal foreground */
  446.             BackColor((long) RScolors[RScurrent->color[1]]);    /* normal Background */
  447.           } /* if */
  448.       } /* if */
  449.     RSa = a;
  450.   } /* RSsetattr */
  451.  
  452. #ifdef    NO_UNIVERSAL
  453. #define LMGetHiliteMode() (* (unsigned char *) 0x0938)
  454. #define LMSetHiliteMode(HiliteModeValue) ((* (unsigned char *) 0x0938) = (HiliteModeValue))
  455. #endif
  456.  
  457. void DoHiliteMode(void)        /* BYU LSC */
  458.   /* enables use of highlighting in place of simple color inversion
  459.     for next QuickDraw operation. */
  460.   {
  461.       
  462.       LMSetHiliteMode(LMGetHiliteMode() & 0x7F);
  463. //    char *p = (char *) 0x938; /* pointer to HiliteMode low-memory global */
  464. //    *p = *p & 0x7f; /* clear the HiliteBit */
  465.   } /* HiliteMode */
  466.  
  467. void RSinvText
  468.   (
  469.     short w, 
  470.     Point curr,
  471.     Point last,
  472.     RectPtr constrain /* don't highlight anything outside this rectangle */
  473.   )
  474.   /* highlights the text from curr to last inclusive. */
  475.   {
  476.     Rect temp, temp2;
  477.     Point lb, ub;
  478.  
  479.     RSsetwind(w);
  480.   /* normalize coordinates with respect to visible area of virtual screen */
  481.     curr.v -= RScurrent->topline;
  482.     curr.h -= RScurrent->leftmarg;
  483.     last.v -= RScurrent->topline;
  484.     last.h -= RScurrent->leftmarg;
  485.  
  486.     if (curr.v == last.v)
  487.       {
  488.       /* highlighted text all on one line */
  489.         if (curr.h < last.h) /* get bounds the right way round */
  490.           {
  491.             ub = curr;
  492.             lb = last;
  493.           }
  494.         else
  495.           {
  496.             ub = last;
  497.             lb = curr;
  498.           } /* if */
  499.         MYSETRECT /* set up rectangle bounding area to be highlighted */
  500.           (
  501.             temp,
  502.             (ub.h + 1) * RScurrent->fwidth,
  503.             ub.v * RScurrent->fheight,
  504.             (lb.h + 1) * RScurrent->fwidth,
  505.             (lb.v + 1) * RScurrent->fheight
  506.           );
  507.         SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
  508.         DoHiliteMode();                        /* BYU LSC */
  509.         InvertRect(&temp2);
  510.       }
  511.     else
  512.       {
  513.       /* highlighting across more than one line */
  514.         if (curr.v < last.v)
  515.             ub = curr;
  516.         else
  517.             ub = last;
  518.         if (curr.v > last.v)
  519.             lb = curr;
  520.         else
  521.             lb = last;
  522.         MYSETRECT /* bounds of first (possibly partial) line to be highlighted */
  523.           (
  524.             temp,
  525.             (ub.h + 1) * RScurrent->fwidth,
  526.             ub.v * RScurrent->fheight,
  527.             RScurrent->width,
  528.             (ub.v + 1) * RScurrent->fheight
  529.           );
  530.         SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
  531.         DoHiliteMode();                        /* BYU LSC */
  532.         InvertRect(&temp2);
  533.         MYSETRECT /* bounds of last (possibly partial) line to be highlighted */
  534.           (
  535.             temp,
  536.             0,
  537.             lb.v * RScurrent->fheight,
  538.             (lb.h + 1) * RScurrent->fwidth,
  539.             (lb.v + 1) * RScurrent->fheight
  540.           );
  541.         SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
  542.         DoHiliteMode();                        /* BYU LSC */
  543.         InvertRect(&temp2);
  544.  
  545.         if (lb.v - ub.v > 1) /* highlight extends across more than two lines */
  546.           {
  547.           /* highlight complete in-between lines */
  548.             SetRect
  549.               (
  550.                 &temp,
  551.                 0,
  552.                 (ub.v + 1) * RScurrent->fheight,
  553.                 RScurrent->width,
  554.                 lb.v * RScurrent->fheight
  555.               );
  556.             SectRect(&temp, constrain, &temp2); /* clip to constraint rectangle */
  557.             DoHiliteMode();                        /* BYU LSC */
  558.             InvertRect(&temp2);
  559.  
  560.           } /* if */
  561.       } /* if */
  562.   } /* RSinvText */
  563.  
  564. void RSdraw
  565.   (
  566.     short w, /* window number */
  567.     short x, /* starting column */
  568.     short y, /* line on which to draw */
  569.     short a, /* text attributes */
  570.     short len, /* length of text to draw */
  571.     char *ptr /* pointer to text */
  572.   )
  573.   /* draws a piece of text (assumed to fit on a single line) in a window,
  574.     using the specified attributes. If any part of the text falls
  575.     within the current selection, it will be highlighted. */
  576.   {
  577.     Rect rect;
  578.     short ys;
  579.  
  580.     if (RSlocal[w].skip)
  581.         return;
  582.     RSsetwind(w);
  583. //    RSsetattr(0);        JMB 2.6.1d4
  584.  
  585.     ys = y * RScurrent->fheight;
  586.     MYSETRECT /* set up rectangle bounding text being drawn */
  587.       (
  588.         rect,
  589.         x * RScurrent->fwidth,
  590.         ys,
  591.         (x + len) * RScurrent->fwidth,
  592.         ys + RScurrent->fheight
  593.       );
  594.  
  595.     if (RSa != a)
  596.         RSsetattr(a);
  597.  
  598.     if (x <= 0)            /* BYU 2.4.12 - Without this, 1 pixel column of reverse */
  599.       rect.left = -3;    /* BYU 2.4.12 - video text does not clear at left margin */
  600.  
  601.     EraseRect(&rect);
  602.  
  603.     if (x <= 0)            /* BYU 2.4.12 - Okay, just putting it back the way it was */
  604.       rect.left = 0;    /* BYU 2.4.12 */
  605.  
  606.     MoveTo(x * RScurrent->fwidth, ys + RScurrent->fascent);
  607.     
  608.     if (RScurrent->monospaced) {
  609.         DrawText(ptr, 0, len);
  610.         }
  611.     else {
  612.         while (len--) {
  613.             /* draw the characters one at a time to defeat the proportional spacing */
  614.             DrawChar(*ptr++);
  615. //            MoveTo((++x) * RScurrent->fwidth, ys);  /*good version */ JMB 2.6.1d4 
  616.             Move(RScurrent->fwidth, 0);
  617.             x++;
  618.             }
  619.         }
  620.  
  621.     if (RScurrent->selected)
  622.         RSinvText(w, *(Point *) &RScurrent->anchor,
  623.             *(Point *) &RScurrent->last, &rect);
  624.   } /* RSdraw */
  625.  
  626. void RSdelcols
  627.   (
  628.     short w,
  629.     short n /* number of columns to scroll */
  630.   )
  631.   /* scrolls the entire visible display of a virtual screen the
  632.     specified number of columns to the left, blanking out
  633.     the newly-revealed area. */
  634.   {
  635.     Rect rect;
  636.  
  637.     if (RSlocal[w].skip)
  638.         return;
  639.     RSsetwind(w);
  640.     MYSETRECT /* bounds of entire text area, for scrolling */
  641.       (
  642.         rect,
  643.         0,
  644.         0,
  645.         RScurrent->width,
  646.         RScurrent->height
  647.       );
  648.     ScrollRect(&rect, -n * RScurrent->fwidth, 0, RSuRgn);
  649.     InvalRgn(RSuRgn);
  650.     ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
  651.     MYSETRECT /* bounds of newly-revealed area */
  652.       (
  653.         rect,
  654.         RScurrent->width - (n * RScurrent->fwidth),
  655.         0,
  656.         RScurrent->width,
  657.         RScurrent->height
  658.       );
  659.     if (RScurrent->selected)
  660.       /* highlight any newly-revealed part of the current selection */
  661.         RSinvText(w, *(Point *) &RScurrent->anchor,
  662.             *(Point *) &RScurrent->last, &rect);
  663.   } /* RSdelcols */
  664.  
  665. void RSdelchars
  666.   (
  667.     short w, /* affected window */
  668.     short x, /* column to delete from */
  669.     short y, /* line on which to do deletion */
  670.     short n /* number of characters to delete */
  671.   )
  672.   /* deletes the specified number of characters from the specified
  673.     position to the right, moving the remainder of the line to the
  674.     left. */
  675.   {
  676.     Rect rect;
  677.  
  678.     if (RSlocal[w].skip)
  679.         return;
  680.     RSsetwind(w);
  681.     RSsetattr(0); /* avoid funny pen modes */
  682.     MYSETRECT /* bounds of area from starting column to end of line */
  683.       (
  684.         rect,
  685.         x * RScurrent->fwidth,
  686.         y * RScurrent->fheight,
  687.         RScurrent->width,
  688.         (y + 1) * RScurrent->fheight
  689.       );
  690.     if ((x + n) * RScurrent->fwidth > RScurrent->width)
  691.       /* deleting to end of line */
  692.         EraseRect(&rect);
  693.     else
  694.       {
  695.       /* scroll remainder of line to the left */
  696.         ScrollRect(&rect, - RScurrent->fwidth * n, 0, RSuRgn);
  697.         InvalRgn(RSuRgn);
  698.            ValidRect(&rect); /* leave newly-revealed area blank */
  699.         if (RScurrent->selected)
  700.           {
  701.           /* highlight any part of selection which lies in newly-blanked area */
  702.             HLock((Handle) RSuRgn);
  703.             RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &((*RSuRgn)->rgnBBox));
  704.             HUnlock((Handle) RSuRgn);
  705.           } /* if */
  706.       } /* if */
  707.   } /* RSdelchars */
  708.  
  709. void RSdellines
  710.   (
  711.     short w, /* affected window */
  712.     short t, /* top line of affected region */
  713.     short b, /* bottom line of affected region */
  714.     short n, /* number of lines to delete */
  715.     short scrolled
  716.       /*
  717.         -ve => cancel current selection, if any;
  718.         +ve => selection has moved up one line;
  719.         0 => don't touch selection
  720.       */
  721.   )
  722.   /* deletes lines at the top of the specified region of a window,
  723.     inserting new blank lines at the bottom, and scrolling up the
  724.     stuff in between. */
  725.   {
  726.     Rect    rect;
  727.     short    RSfheightTimesn, RSfheightTimesbplus1;
  728.  
  729.     if (RSlocal[w].skip)
  730.         return;
  731.  
  732.     RSsetwind(w);
  733.     RSsetConst(w);
  734.     RSsetattr(0); /* avoid funny pen modes */
  735.  
  736.     if (scrolled)
  737.       {
  738.         if (RScurrent->selected && scrolled < 0)
  739.           {
  740.           /* unhighlight and cancel current selection */
  741.             RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &noConst);
  742.             RScurrent->selected = 0;
  743.           }
  744.         else
  745.           {
  746.             RScurrent->last.v -= 1;        /* Subtract one from each of the */
  747.             RScurrent->anchor.v -= 1;    /* vertical Selection components */
  748.           } /* if */
  749.       } /* if */
  750.  
  751.     rect.left = -1;                            /* BYU 2.4.12 - necessary */
  752.     rect.right = RScurrent->width;
  753.     rect.top = t * RScurrent->fheight;
  754.     RSfheightTimesbplus1 = (b + 1) * RScurrent->fheight;
  755.     rect.bottom = RSfheightTimesbplus1;
  756.  
  757.   /* adjust the update region to track the scrolled window contents */
  758.       RSfheightTimesn = RScurrent->fheight * n;
  759.     OffsetRgn(((WindowPeek) RScurrent->window)->updateRgn,
  760.         0, -RSfheightTimesn);
  761.     ScrollRect(&rect, 0, -RSfheightTimesn , RSuRgn);
  762.     RSsetattr(VSIw->attrib); /* restore mode for text drawing */
  763.     InvalRgn(RSuRgn);
  764.  
  765.   /* validate the area containing the newly-inserted blank lines. */
  766.   /* any necessary redrawing in newly-revealed area will be done by caller */
  767.     MYSETRECT
  768.       (
  769.         rect,
  770.         0,
  771.         (b - n + 1) * RScurrent->fheight - 1,
  772.         RScurrent->width,
  773.         RSfheightTimesbplus1 + 1
  774.       );
  775.  
  776.     ValidRect(&rect);
  777.   } /* RSdellines */
  778.  
  779. void RSerase
  780.   (
  781.     short w, /* affected window */
  782.     short x1, /* left column */
  783.     short y1, /* top line */
  784.     short x2, /* right column */
  785.     short y2 /* bottom line */
  786.   )
  787.   /* erases a rectangular portion of the screen display, preserving
  788.     the selection highlight. */
  789.   {
  790.     Rect rect;
  791.  
  792.     if (RSlocal[w].skip)
  793.         return;
  794.     RSsetwind(w);
  795.     RSsetattr(0); /* avoid funny pen modes */
  796.     SetRect
  797.       (
  798.         &rect,
  799.         x1 * RScurrent->fwidth,
  800.         y1 * RScurrent->fheight,
  801.         (x2 + 1) * RScurrent->fwidth - 1,
  802.         (y2 + 1) * RScurrent->fheight + 1
  803.       );
  804.     if (rect.left <= 0)                        /* little buffer strip on left */
  805.         rect.left = CHO;
  806.     if (rect.right >= RScurrent->width - 1)
  807.         rect.right = RScurrent->rwidth - 2;    /* clear to edge of window, including edge strip */
  808.     if (rect.bottom >= RScurrent->height - 2)
  809.         rect.bottom = RScurrent->rheight + 1;    /* clear to bottom edge also */
  810.     EraseRect(&rect);
  811.     if (RScurrent->selected)
  812.       /* highlight any part of the selection within the cleared area */
  813.         RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &rect);
  814.   } /* RSerase */
  815.  
  816. void RSinslines
  817.   (
  818.     short w, /* affected window */
  819.     short t, /* where to insert blank lines */
  820.     short b, /* bottom of area to scroll */
  821.     short n, /* number of lines to insert */
  822.     short scrolled /* -ve <=> cancel current selection, if any */
  823.   )
  824.   /* inserts blank lines at the top of the given area of the display,
  825.     scrolling the rest of it down. */
  826.   {
  827.     Rect rect;
  828.  
  829.     if (RSlocal[w].skip)
  830.         return;
  831.     RSsetwind(w);
  832.     RSsetConst(w);
  833.     RSsetattr(0); /* avoid funny pen modes */
  834.     if (RScurrent->selected && (scrolled < 0))
  835.       {
  836.       /* unhighlight and cancel selection */
  837.         RSinvText(w, *(Point *) &RScurrent->anchor,
  838.             *(Point *) &RScurrent->last, &noConst);
  839.         RScurrent->selected = 0;
  840.       } /* if */
  841.     rect.left = -1;                        /* BYU 2.4.12 - necessary */
  842.     rect.right = RScurrent->width;
  843.     rect.top = t * RScurrent->fheight;
  844.     rect.bottom = (b + 1) * RScurrent->fheight;
  845.   /* adjust the update region to track the scrolled window contents */
  846.     OffsetRgn(((WindowPeek) RScurrent->window)->updateRgn,
  847.         0, RScurrent->fheight * n);
  848.     ScrollRect(&rect, 0, RScurrent->fheight * n, RSuRgn);
  849.     InvalRgn(RSuRgn);
  850.   /* newly-inserted area is already blank -- validate it to avoid redrawing. */
  851.   /* any necessary redrawing will be done by caller */
  852.     SetRect(&rect, 0, t * RScurrent->fheight - 1,
  853.         RScurrent->width, (t + n) * RScurrent->fheight + 1);
  854.     ValidRect(&rect);
  855.   } /* RSinslines */
  856.  
  857. void RSinscols
  858.   (
  859.     short w,
  860.     short n /* number of columns to insert */
  861.   )
  862.   /* inserts blank columns at the left side of the text display in
  863.     the specified window, scrolling its current contents to the right.
  864.     Maintains the selection highlight, but doesn't move the selection.
  865.     Doesn't even unhighlight text which moves out of the selection area. */
  866.   {
  867.     Rect rect;
  868.  
  869.     if (RSlocal[w].skip)
  870.         return;
  871.     RSsetwind(w);
  872.     SetRect /* bounds of entire text area */
  873.       (
  874.         &rect,
  875.         0,
  876.         0,
  877.         RScurrent->width,
  878.         RScurrent->height
  879.       );
  880.     ScrollRect(&rect, n * RScurrent->fwidth, 0, RSuRgn);
  881.     InvalRgn(RSuRgn);
  882.     ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
  883.     SetRect /* bounds of newly-inserted blank area */
  884.       (
  885.         &rect,
  886.         0,
  887.         0,
  888.         (n + 1) * RScurrent->fwidth - 1,
  889.         RScurrent->height
  890.       );
  891.     if (RScurrent->selected)
  892.       /* highlight any part of the selection in the newly-blanked area */
  893.         RSinvText(w, *(Point *) &RScurrent->anchor, *(Point *) &RScurrent->last, &rect);
  894.   } /* RSinscols */
  895.  
  896. void RSinsstring
  897.   (
  898.     short w, /* affected window */
  899.     short x, /* starting column at which to insert */
  900.     short y, /* line on which to insert */
  901.     short a, /* attributes for inserted text */
  902.     short len, /* length of inserted text */
  903.     char *ptr /* pointer to inserted text */
  904.   )
  905.   /* inserts a string of characters at the specified position, scrolling
  906.     the rest of the line to the right. Highlights any part of the newly-
  907.     inserted text lying within the current selection. */
  908.   {
  909.     Rect rect;
  910.  
  911.     if (RSlocal[w].skip)
  912.         return;
  913.     RSsetwind(w);
  914.     SetRect /* bounds of part of line from specified position to end of line */
  915.       (
  916.         &rect,
  917.         x * RScurrent->fwidth,
  918.         y * RScurrent->fheight,
  919.         RScurrent->width,
  920.         (y + 1) * RScurrent->fheight
  921.       );
  922.     ScrollRect(&rect, len * RScurrent->fwidth, 0, RSuRgn); /* scroll remainder of line to the right */
  923.     if (RSa != a)
  924.         RSsetattr(a);
  925.     InvalRgn(RSuRgn);
  926.     ValidRect(&rect); /* any necessary redrawing in newly-revealed area will be done by caller */
  927.     SetRect /* bounds area to contain inserted string */
  928.       (
  929.         &rect,
  930.         x * RScurrent->fwidth,
  931.         y * RScurrent->fheight,
  932.         (x + len) * RScurrent->fwidth,
  933.         (y + 1) * RScurrent->fheight
  934.       );
  935.     EraseRect(&rect); /* erase area to appropriate background */
  936.     MoveTo
  937.       (
  938.         x * RScurrent->fwidth,
  939.         y * RScurrent->fheight + RScurrent->fascent
  940.       );
  941.     DrawText(ptr, 0, len);
  942.     if (RScurrent->selected)
  943.       /* highlight any part of selection covering the newly-inserted text */
  944.         RSinvText(w, *(Point *) &RScurrent->anchor,
  945.             *(Point *) &RScurrent->last, &rect);
  946.   } /* RSinsstring */
  947.  
  948. void RSsendstring
  949.   (
  950.     short w, /* which terminal window */
  951.     char *ptr, /* pointer to data */
  952.     short len /* length of data */
  953.   )
  954.   /* sends some data to the host along the connection associated
  955.     with the specified window. */
  956.   {
  957. #ifdef NCSA_TELNET
  958.     short temp;
  959.  
  960.     temp = findbyVS(w);
  961.     if (temp < 0)
  962.         return;
  963. /*    if (!screens[scrn].lmflag)    */
  964.         netwrite(screens[temp].port, ptr, len);
  965.         netpush(screens[temp].port);                /* BYU 2.4.18 - for Diab systems? */
  966. /*    else 
  967.         {
  968.         sprintf(screens[scrn].kbbuf,"%s",ptr);
  969.         screens[scrn].kblen += len;
  970.         if (screens[scrn].echo) parse(&screens[scrn],ptr,len);
  971.         }*/
  972.         
  973. #else
  974.     while (len--)
  975.         putu(*ptr++);
  976. #endif
  977.   } /* RSsendstring */
  978.  
  979. void RSmargininfo
  980.   (
  981.     short w,
  982.     short total, /* number of invisible character positions (screen width less visible width) */
  983.     short current /* leftmost visible character position */
  984.   )
  985.   /* updates the horizontal scroll bar and associated variables
  986.     to reflect the current view of the virtual screen within the
  987.     specified window. */
  988.   {
  989.     RSlocal[w].leftmarg = current;            /* Adjust local vars */
  990.     if (RSlocal[w].lcurrent != current)
  991.         SetCtlValue(RSlocal[w].left, (RSlocal[w].lcurrent = current));
  992.     if (RSlocal[w].lmax != total)
  993.         SetCtlMax(RSlocal[w].left, (RSlocal[w].lmax = total));
  994.   } /* RSmargininfo */
  995.  
  996. #if 0
  997. //void RSbufinfo
  998.   (
  999.     short w, /* affected window */
  1000.     short total, /* number of lines of scrollback */
  1001.     short current, /* current topmost visible line */
  1002.     short bottom /* current bottommost visible line */
  1003.   )
  1004.   /* readjusts the vertical scroll bar and associated variables
  1005.     to reflect the current view of the virtual screen within the
  1006.     specified window. */
  1007.   {
  1008.     RSdata *RSthis;
  1009.     short newmax;
  1010.  
  1011.     RSthis = RSlocal + w;
  1012.  
  1013.     newmax = (VSgetlines(w) - 1) - (bottom - current);
  1014.  
  1015.     RSthis->topline = current;            /* Adjust local vars */
  1016.  
  1017.     if (RSthis->min != -total)
  1018.       {
  1019.         SetCtlMin(RSthis->scroll, (RSthis->min = -total));
  1020.         SetCtlValue(RSthis->scroll, (RSthis->current = current));
  1021.       } /* if */
  1022.  
  1023.     if (RSthis->current != current)
  1024.         SetCtlValue(RSthis->scroll, (RSthis->current = current));
  1025.  
  1026.     if (RSthis->max != newmax)
  1027.       {
  1028.         SetCtlMax(RSthis->scroll, (RSthis->max = newmax));
  1029.         SetCtlValue(RSthis->scroll, (RSthis->current = current));
  1030.       } /* if */
  1031.  
  1032.   } /* RSbufinfo */
  1033. #endif
  1034.  
  1035. void RSbufinfo
  1036.   (
  1037.     short w, /* affected window */
  1038.     short total, /* number of lines of scrollback */
  1039.     short current, /* current topmost visible line */
  1040.     short bottom /* current bottommost visible line */
  1041.   )
  1042.   /* readjusts the vertical scroll bar and associated variables
  1043.     to reflect the current view of the virtual screen within the
  1044.     specified window. */
  1045.   {
  1046.     RSdata *RSthis;
  1047.     short newmax;
  1048.  
  1049.     RSthis = RSlocal + w;
  1050.  
  1051.     newmax = (VSgetlines(w) - 1) - (bottom - current);
  1052.  
  1053.     RSthis->topline = current;            /* Adjust local vars */
  1054.  
  1055.     if (RSthis->min != -total)
  1056.       {
  1057. //        SetCtlMin(RSthis->scroll, (RSthis->min = -total)); JMB 2.6.1d4
  1058.         (**RSthis->scroll).contrlMin = (RSthis->min = -total);    // JMB 2.6.1d4
  1059. //        SetCtlValue(RSthis->scroll, (RSthis->current = current)); JMB 2.6.1d4
  1060.       } /* if */
  1061.  
  1062.     if (RSthis->current != current)
  1063.         SetCtlValue(RSthis->scroll, (RSthis->current = current));
  1064.  
  1065.     if (RSthis->max != newmax)
  1066.       {
  1067. //        SetCtlMax(RSthis->scroll, (RSthis->max = newmax)); JMB 2.6.1d4
  1068.         (**RSthis->scroll).contrlMax = (RSthis->max = newmax);    // JMB 2.6.1d4
  1069. //        SetCtlValue(RSthis->scroll, (RSthis->current = current)); JMB 2.6.1d4
  1070.       } /* if */
  1071.  
  1072.   } /* RSbufinfo */
  1073.  
  1074. GrafPtr RSgetwindow
  1075.   (
  1076.     short w
  1077.   )
  1078.   /* returns a pointer to the Mac window structure for the
  1079.     specified terminal window. */
  1080.   {
  1081.     return(RSlocal[w].window);
  1082.   } /* RSgetwindow */
  1083.  
  1084. void RSattach
  1085.   (
  1086.     short w,
  1087.     GrafPtr wind
  1088.   )
  1089.   /* attaches the specified window to a virtual screen, for
  1090.     use for displaying that screen. */
  1091.   {
  1092.     RSlocal[w].window = wind;
  1093.     RSlocal[w].selected = 0;
  1094.     RScurrent->cursorstate = 0;    /* BYU 2.4.11 - cursor off */
  1095.     SetPort(wind);
  1096. #if 1                                /* BYU */
  1097.     RSTextFont(FONT,FSIZE,0);            /* BYU */
  1098. #else
  1099.     TextFont(FONT);
  1100. #endif
  1101.     TextSize(FSIZE);
  1102.     if (!RScolor)
  1103.         TextMode(srcXor);            /* Xor mode*/
  1104.     else
  1105.         TextMode(srcCopy);
  1106.     RSw = -1;    /* make sure we don't write in wrong place */
  1107.   } /* RSattach */
  1108.  
  1109. void RSdetach
  1110.   (
  1111.     short w
  1112.   )
  1113.   /* detaches the window for the specified virtual screen. */
  1114.   {
  1115.     RSlocal[w].window = 0L;
  1116.     RSw = -1;    /* make sure we don't write in wrong place */
  1117.   } /* RSdetach */
  1118.  
  1119. short RSfindvwind
  1120.   (
  1121.     GrafPtr wind
  1122.   )
  1123.   /* returns the number of the virtual screen associated with
  1124.     the specified window, or -4 if not found. */
  1125.   {
  1126.     short
  1127.         i = 0;
  1128.     while ((RSlocal[i].window != wind) && (i < MaxRS))
  1129.         i++;
  1130.     if ((RSlocal[i].window == 0L) || (i >= MaxRS))
  1131.         return(-4);
  1132.     else
  1133.         return(i);
  1134.   } /* RSfindvwind */
  1135.  
  1136. short RSfindscroll                /* Find screen index by control*/
  1137.   (
  1138.     ControlHandle control,
  1139.     short *n
  1140.   )
  1141.   /* finds the window to which the given scroll bar belongs.
  1142.     Returns the window number in *n if found, and a function
  1143.     result of 1 for a vertical scroll bar, 2 for a horizontal
  1144.     one, or -1 if the window wasn't found. */
  1145.   {
  1146.   /* look for a vertical scroll bar */
  1147.     *n = 0;
  1148.     while ((*n < MaxRS) && (control != RSlocal[*n].scroll))
  1149.         (*n)++;
  1150.     if (*n < MaxRS)
  1151.         return (1); /* found it */
  1152.   /* look for a horizontal scroll bar */
  1153.     *n = 0;
  1154.     while ((*n < MaxRS) && (control != RSlocal[*n].left))
  1155.         (*n)++;
  1156.     if (*n < MaxRS)
  1157.         return (2); /* found it */
  1158.     return(-1); /* not found */
  1159.   } /* RSfindscroll */
  1160.  
  1161. void RSregnconv
  1162.   (
  1163.     RgnHandle regn,
  1164.     short *x1, /* left (output) */
  1165.     short *y1, /* top (output) */
  1166.     short *x2, /* right (output) */
  1167.     short *y2, /* bottom (output) */
  1168.     short fh, /* font character height */
  1169.     short fw /* font character width */
  1170.   )
  1171.   /* converts the bounding box of the specified QuickDraw region
  1172.     into units of character positions (using the specified character
  1173.     height and width) and returns the results in *x1, *y1, *x2 and *y2. */
  1174.   {
  1175.     HLock((Handle) regn);
  1176.     *y1 = ((*regn)->rgnBBox.top) / fh;
  1177.     *y2 = (((*regn)->rgnBBox.bottom) + fh - 1) / fh;
  1178.     *x1 = ((*regn)->rgnBBox.left) / fw;
  1179.     *x2 = (((*regn)->rgnBBox.right) + fw - 1) / fw;
  1180.     HUnlock((Handle) regn);
  1181.     if (*x1 < 0)
  1182.         *x1 = 0;
  1183.     if (*y1 < 0)
  1184.         *y1 = 0;
  1185.     if (*x2 < 0)
  1186.         *x2 = 0;
  1187.     if (*y2 < 0)
  1188.         *y2 = 0;
  1189. #ifdef WHONEEDSIT
  1190.     if (*x1> VSIw->maxwidth)
  1191.         *x1 = VSIw->maxwidth;
  1192.     if (*x2 > VSIw->maxwidth)
  1193.         *x2 = VSIw->maxwidth;
  1194.     if (*y1 > VSIw->lines)
  1195.         *y1 = VSIw->lines;
  1196.     if (*y2 > VSIw->lines)
  1197.         *y2 = VSIw->lines;
  1198. #endif WHONEEDSIT
  1199.   } /* RSregnconv */
  1200.  
  1201. short RSupdate
  1202.   (
  1203.     GrafPtr wind
  1204.   )
  1205.   /* does updating for the specified window, if it's one of mine.
  1206.     Returns zero iff it is. */
  1207.   {
  1208.     short w, x1, x2, y1, y2;
  1209.  
  1210.     w = RSfindvwind(wind);
  1211.     if (RSsetwind(w) < 0)
  1212.         return(-1); /* not one of mine */
  1213.     BeginUpdate(wind);
  1214.     RSregnconv /* find bounds of text area needing updating */
  1215.       (
  1216.         wind->visRgn,
  1217.         &x1, &y1, &x2, &y2,
  1218.         RScurrent->fheight, RScurrent->fwidth
  1219.       );
  1220.     VSredraw(w, x1, y1, x2, y2); /* draw that text */
  1221.   /* We must reset, less we risk looking UGLY as sin... */
  1222.     BackPat(PATTERN(qd.white));
  1223.     PenPat(PATTERN(qd.black));
  1224.     if (RScolor)
  1225.       {
  1226.         PmForeColor(0);
  1227.         PmBackColor(1);
  1228.       }
  1229.     else
  1230.       {
  1231.         ForeColor((long) RScolors[ RScurrent->color[0]]);        /* normal foreground */
  1232.         BackColor((long) RScolors[ RScurrent->color[1]]);        /* normal Background */
  1233.       } /* if */
  1234.     RSa = -1;
  1235.     PenMode(patOr);
  1236.     DrawGrowIcon(wind);
  1237.     PenMode(patCopy);
  1238.     //DrawControls(wind);
  1239.     UpdtControl(wind, wind->visRgn);
  1240.  
  1241.     EndUpdate(wind);
  1242.     return(0);
  1243.   } /* RSupdate */
  1244.  
  1245. #ifdef FASTERCOMMENTED
  1246.  
  1247. RSupdprint(WindowPeek wind)
  1248.   /* debugging routine: displays bounds (in character units) of
  1249.     update region of specified window. */
  1250.   {
  1251.     short x, y, z, w;
  1252.     char tbuf[50];
  1253.  
  1254.     RSregnconv(wind->updateRgn, &x, &y, &z, &w);
  1255. //    sprintf(tbuf, "RSregnconv: %d,%d,%d,%d", x, y, z, w);
  1256. //    putln(tbuf);
  1257.   } /* RSupdprint */
  1258.  
  1259. #endif
  1260.  
  1261. Point getlocalmouse(GrafPtr wind)
  1262.   /* returns the current mouse position in coordinates local
  1263.     to the specified window. Leaves the current grafPort set
  1264.     to that window. */
  1265.   {
  1266.     Point temp;
  1267.  
  1268.     SetPort(wind);
  1269.     GetMouse(&temp);
  1270.     return(temp);
  1271.   } /* getlocalmouse */
  1272.  
  1273. #define    Fwidthhalf    FWidth/2
  1274.  
  1275. Point normalize(Point in, short w)
  1276.   /* converts in from a pixel position in local coordinates to
  1277.     a character cell position within the virtual screen corresponding
  1278.     to the specified window. Constrains the position to lie within
  1279.     the currently-visible region of the screen, autoscrolling the
  1280.     screen if necessary. */
  1281.   {
  1282.  
  1283.     if (in.v <0)
  1284.       {
  1285.         in.v = 0;
  1286.         VSscrolback(w, 1);
  1287.       } /* if */
  1288.     if (in.v > RSlocal[w].height)
  1289.       {
  1290.         in.v = RSlocal[w].height;
  1291.         VSscrolforward(w, 1);
  1292.       } /* if */
  1293.     in.v = in.v / FHeight;
  1294.  
  1295.     if (in.h < 0)
  1296.       {
  1297.         in.h = -1;
  1298.         VSscrolleft(w, 1);
  1299.       } /* if */
  1300.     if (in.h > RSlocal[w].width)
  1301.       {
  1302.         in.h = RSlocal[w].width;
  1303.         VSscrolright(w, 1);
  1304.       } /* if */
  1305.   /* in.h = (in.h + Fwidthhalf) / FWidth - 1; */
  1306.   /* the MPW C 3.0 compiler has a bug in its register allocation */
  1307.   /* which keeps the above line from working. So, replace it with this: */
  1308.     in.h = in.h + Fwidthhalf;
  1309.     in.h = in.h / FWidth - 1;
  1310.   /* note the bug has been fixed in the 3.1 compiler. */
  1311.   /* convert to virtual screen coordinates */
  1312.     in.v += RSlocal[w].topline;
  1313.     in.h += RSlocal[w].leftmarg;
  1314.     return(in);
  1315.   } /* normalize */
  1316.  
  1317. /*--------------------------------------------------------------------------*/
  1318. /* HandleDoubleClick                                                        */
  1319. /* This is the routine that does the real dirty work.  Since it is not a    */
  1320. /* true TextEdit window, we have to kinda "fake" the double clicking.  By    */
  1321. /* this time, we already know that a double click has taken place, so check    */
  1322. /* the chars to the left and right of our location, and select all chars     */
  1323. /* that are appropriate    -- SMB                                                */
  1324. /*--------------------------------------------------------------------------*/
  1325. static    void HandleDoubleClick(short w, short modifiers)                                                    
  1326. {                                                                                
  1327.     Point    leftLoc, rightLoc, curr, oldcurr;                                                    
  1328.     long    mySize;                                                            
  1329.     char    theChar[5];                                                            
  1330.     short    mode = -1, newmode, foundEnd=0;                                                            
  1331.                                                                                 
  1332.     RSsetConst(w);                                                                /* get window dims */                            
  1333.     leftLoc = RSlocal[w].anchor;                                    /* these two should be the same */                            
  1334.     rightLoc = RSlocal[w].last;                                    
  1335.                                                                                 
  1336.     while(!foundEnd)                                                            /* scan to the right first */                                                        
  1337.         {                                                                        
  1338.         mySize = VSgettext(w,rightLoc.h, rightLoc.v, rightLoc.h+1, rightLoc.v,    
  1339.             (char *)theChar,(long)1,"\015",0);                                    
  1340.         if(mySize ==0 || isspace(*theChar))                                    /* stop if not a letter */            
  1341.             foundEnd =1;                                                        
  1342.         else rightLoc.h++;                                                        
  1343.         }                                                                        
  1344.                                                                                 
  1345.     foundEnd =0;                                                                
  1346.     while(!foundEnd)                                                            /* ...and then scan to the left */                                                            
  1347.         {                                                                        
  1348.         mySize = VSgettext(w,leftLoc.h-1, leftLoc.v, leftLoc.h, leftLoc.v,        
  1349.             (char *)theChar,(long)1,"\015",0);                                    
  1350.         if(mySize ==0 || isspace(*theChar))                                        /* STOP! */        
  1351.             foundEnd =1;                                                        
  1352.         else leftLoc.h--;                                                        
  1353.         }                                                                        
  1354.                                                                                 
  1355.     if (leftLoc.h != rightLoc.h) {        /* we selected something */
  1356.         RSlocal[w].anchor = leftLoc;    /* new left bound */
  1357.         RSlocal[w].last = rightLoc;        /* and a matching new right bound */
  1358.         RSlocal[w].selected = 1;        /* give me credit for the selection I just made */
  1359.         RSinvText(w, RSlocal[w].anchor,        /* time to show it off */
  1360.             RSlocal[w].last, &noConst);
  1361.  
  1362.         if (modifiers & cmdKey) {        // Possible URL selection
  1363.             ParseURL(w);
  1364.             }
  1365.         else {                                                                        
  1366.     
  1367.             curr.h = 0; curr.v = 0;
  1368.     
  1369.             while (StillDown()) {
  1370.               /* wait for mouse position to change */
  1371.                 do {
  1372.                     oldcurr = curr;
  1373.                     curr = normalize(getlocalmouse(RSlocal[w].window), w);
  1374.                     } while (EqualPt(curr, oldcurr) && StillDown());
  1375.         
  1376.                 
  1377.                 if ((curr.v < leftLoc.v) || ((curr.v == leftLoc.v) && (curr.h < leftLoc.h))) {
  1378.                     newmode = 1;    // up
  1379.                     }
  1380.                 else if ((curr.v > leftLoc.v) || ((curr.v == leftLoc.v) && (curr.h > rightLoc.h))) {
  1381.                     newmode = 2;    // down
  1382.                     }
  1383.                 else 
  1384.                     newmode = -1;    // inside dbl-clicked word
  1385.                     
  1386.                 /* toggle highlight state of text between current and last mouse positions */
  1387.                 if (mode == -1) {
  1388.                     if (newmode == 2) {
  1389.                         RSlocal[w].anchor = leftLoc;
  1390.                         RSinvText(w, curr, rightLoc, &noConst);
  1391.                         RSlocal[w].last = curr;
  1392.                         }
  1393.                     if (newmode == 1) {
  1394.                         RSlocal[w].anchor = rightLoc;
  1395.                         RSinvText(w, curr, leftLoc, &noConst);
  1396.                         RSlocal[w].last = curr;
  1397.                         }
  1398.                     }
  1399.     
  1400.                 if (mode == 1) {
  1401.                     if (newmode == 2) {
  1402.                         RSlocal[w].anchor = leftLoc;
  1403.                         RSinvText(w, oldcurr, leftLoc, &noConst);
  1404.                         RSinvText(w, rightLoc, curr, &noConst);
  1405.                         RSlocal[w].last = curr;
  1406.                         }
  1407.                     if (newmode == -1) {
  1408.                         RSlocal[w].anchor = leftLoc;
  1409.                         RSinvText(w, oldcurr, leftLoc, &noConst);
  1410.                         RSlocal[w].last = rightLoc;
  1411.                         }
  1412.                     if (newmode == mode) {
  1413.                         RSinvText(w, oldcurr, curr, &noConst);
  1414.                         RSlocal[w].last = curr;
  1415.                         }
  1416.                     }
  1417.                 
  1418.                 if (mode == 2) {
  1419.                     if (newmode == 1) {
  1420.                         RSlocal[w].anchor = rightLoc;
  1421.                         RSinvText(w, oldcurr, rightLoc, &noConst);
  1422.                         RSinvText(w, leftLoc, curr, &noConst);
  1423.                         RSlocal[w].last = curr;
  1424.                         }
  1425.                     if (newmode == -1) {
  1426.                         RSlocal[w].anchor = leftLoc;
  1427.                         RSinvText(w, oldcurr, rightLoc, &noConst);
  1428.                         RSlocal[w].last = rightLoc;
  1429.                         }
  1430.                     if (newmode == mode) {
  1431.                         RSinvText(w, oldcurr, curr, &noConst);
  1432.                         RSlocal[w].last = curr;
  1433.                         }
  1434.                     }
  1435.                     
  1436.                 mode = newmode;
  1437.                 } /* while */
  1438.             }
  1439.         }    
  1440. }
  1441.     
  1442.  
  1443. void    RSsortAnchors(short w)
  1444. {
  1445.     Point    temp;
  1446.     
  1447.     if (RSlocal[w].anchor.v > RSlocal[w].last.v) {
  1448.         temp = RSlocal[w].anchor;
  1449.         RSlocal[w].anchor = RSlocal[w].last;
  1450.         RSlocal[w].last = temp;
  1451.         }
  1452.         
  1453.     if ((RSlocal[w].anchor.v == RSlocal[w].last.v) && (RSlocal[w].anchor.h > RSlocal[w].last.h)) {
  1454.         temp = RSlocal[w].anchor;
  1455.         RSlocal[w].anchor = RSlocal[w].last;
  1456.         RSlocal[w].last = temp;
  1457.         }
  1458. }    
  1459.  
  1460. /*------------------------------------------------------------------------------*/
  1461. /* RSselect                                                                        */
  1462. /* Handle the mouse down in the session window.  All we know so far is that it    */
  1463. /* is somewhere in the content window, and it is NOT an option - click.            */
  1464. /* Double clicking now works -- SMB                                                */
  1465. // And I fixed it so it works correctly.  Grrrr... - JMB
  1466. //    WARNING: Make sure RSlocal[w].selected is 1 when doing selections.  If it is
  1467. //        zero, the autoscrolling routines will seriously hose the selection drawing.
  1468. //        Heed this advice, it took me two hours to find the cause of this bug! - JMB
  1469.  
  1470.   /* called on a mouse-down in the text display area of the
  1471.     active window. Creates or extends the highlighted selection
  1472.     within that window, autoscrolling as appropriate if the user
  1473.     drags outside the currently visible part of the display. */
  1474. void RSselect( short w, Point pt, EventRecord theEvent)
  1475. {
  1476.     static    long     lastClick = 0;
  1477.     static     Point     lastClickLoc = {0,0};
  1478.     GrafPtr tempwndo;
  1479.     Point    curr, temp;
  1480.     long    clickTime;
  1481.     short    shift = (theEvent.modifiers & shiftKey);
  1482.     
  1483.     RSsetConst(w);
  1484.     tempwndo = RSlocal[w].window;
  1485.     
  1486.     curr = normalize(pt, w);
  1487.     clickTime = TickCount();
  1488.     
  1489.     if  ( ( EqualPt(RSlocal[w].anchor, curr) || EqualPt(RSlocal[w].anchor, RSlocal[w].last) )
  1490.             &&  ((clickTime - lastClick) <= GetDblTime())
  1491.             && EqualPt(curr, lastClickLoc)) {
  1492.         /* NCSA: SB - check to see if this is a special click */
  1493.         /* NCSA: SB - It has to be in the right time interval, and in the same spot */
  1494.         curr = RSlocal[w].anchor = RSlocal[w].last = normalize(pt, w);
  1495.         HandleDoubleClick(w, theEvent.modifiers);
  1496.         RSlocal[w].selected = 1;
  1497.         lastClick = clickTime;
  1498.         lastClickLoc = curr;
  1499.         }
  1500.     else {
  1501.         lastClick = clickTime;
  1502.         lastClickLoc = curr;
  1503.         if (RSlocal[w].selected) {
  1504.             if (!shift) {
  1505.               /* unhighlight current selection */
  1506.                 RSinvText(w, RSlocal[ w].anchor, RSlocal[w].last, &noConst);
  1507.               /* start new selection */
  1508.                 curr = RSlocal[w].last = RSlocal[w].anchor = normalize(pt, w);
  1509.             }
  1510.             else {
  1511.                 RSsortAnchors(w);
  1512.                 if ((curr.v < RSlocal[w].anchor.v) || ((curr.v == RSlocal[w].anchor.v) && (curr.h < RSlocal[w].anchor.h))) {
  1513.                     temp = RSlocal[w].anchor;
  1514.                     RSlocal[w].anchor = RSlocal[w].last;
  1515.                     RSlocal[w].last = temp;
  1516.                     }
  1517.                 }
  1518.           }
  1519.         else
  1520.           {
  1521.           /* start new selection */
  1522.             curr = RSlocal[w].anchor = RSlocal[w].last = normalize(pt, w);
  1523.             RSlocal[w].selected = 1;
  1524.             }
  1525.             
  1526.         while (StillDown())
  1527.           {
  1528.           /* wait for mouse position to change */
  1529.             do {
  1530.                 curr = normalize(getlocalmouse(tempwndo), w);
  1531.                 } while (EqualPt(curr, RSlocal[w].last) && StillDown());
  1532.     
  1533.           /* toggle highlight state of text between current and last mouse positions */
  1534.             RSinvText(w, curr, RSlocal[w].last, &noConst);
  1535.             RSlocal[w].last = curr;
  1536.           } /* while */
  1537.         }
  1538.  
  1539.     
  1540.     if (EqualPt(RSlocal[w].anchor, RSlocal[w].last)) RSlocal[w].selected = 0;
  1541.         else RSlocal[w].selected = 1;
  1542.     SetMenusForSelection((short)RSlocal[w].selected);
  1543.   } /* RSselect */
  1544.  
  1545. void RSactivate
  1546.   (
  1547.     short w
  1548.   )
  1549.   /* handles an activate event for the specified window. */
  1550.   {
  1551.     RSsetConst(w);
  1552.   /* display the grow icon */
  1553.     DrawGrowIcon(RSlocal[w].window);
  1554.   /* and activate the scroll bars */
  1555.     if (RSlocal[w].scroll != 0L)
  1556.         HiliteControl(RSlocal[w].scroll, 0);
  1557.     if (RSlocal[w].left != 0L)
  1558.         HiliteControl(RSlocal[w].left, 0);
  1559.   } /* RSactivate */
  1560.  
  1561. void RSdeactivate
  1562.   (
  1563.     short w
  1564.   )
  1565.   /* handles a deactivate event for the specified window. */
  1566.   {
  1567.     RSsetConst(w);
  1568.   /* update the appearance of the grow icon */
  1569.     DrawGrowIcon(RSlocal[w].window); 
  1570.   /* and deactivate the scroll bars */
  1571.     if (RSlocal[w].scroll != 0L)
  1572.         HiliteControl(RSlocal[w].scroll, 255);
  1573.     if (RSlocal[w].left != 0L)
  1574.         HiliteControl(RSlocal[w].left, 255);
  1575.   } /* RSdeactivate */
  1576.  
  1577. char **RSGetTextSel
  1578.   (
  1579.     short w, /* window to look at */
  1580.     short table /* nonzero for "table" mode, i e
  1581.         replace this many (or more) spaces with a single tab. */
  1582.   )
  1583.   /* returns the contents of the current selection as a handle,
  1584.     or nil if there is no selection. */
  1585.   {
  1586.     char **charh, *charp;
  1587.     short maxwid;
  1588.     long realsiz;
  1589.     Point Anchor,Last;
  1590.  
  1591.     if (!RSlocal[w].selected)
  1592.         return(0L);    /* No Selection */
  1593.     maxwid = VSmaxwidth(w);
  1594.     Anchor = RSlocal[w].anchor;
  1595.     Last = RSlocal[w].last;
  1596.     
  1597.     realsiz = Anchor.v - Last.v;
  1598.     if (realsiz < 0)
  1599.         realsiz = - realsiz;
  1600.     realsiz ++;                                /* lines 2,3 selected can be 2 lines */
  1601.     realsiz *= (maxwid + 2);
  1602. //    sprintf(tempc, "Size of block=%d", realsiz);
  1603. //    putln(tempc);
  1604.     charh = NewHandle(realsiz);
  1605.     if (charh == 0L)
  1606.         return((char **) -1L);                /* Boo Boo return */
  1607.     HLock(charh);
  1608.     charp = *charh;
  1609.     realsiz = VSgettext(w, Anchor.h, Anchor.v, Last.h, Last.v,
  1610.         charp, realsiz, "\015", table);
  1611. //    putln("unlocking");
  1612.     HUnlock(charh);
  1613.     SetHandleSize(charh, realsiz);
  1614. //    sprintf(tempc, "Size of clip=%d", realsiz);
  1615. //    putln(tempc);
  1616.     return(charh);
  1617.   }  /* RSGetTextSel */
  1618.  
  1619. void    RSsetsize( short w, short v, short h)
  1620. /*    saves the new size settings for a window, and repositions
  1621.     the scroll bars accordingly. */
  1622. {
  1623.     RSlocal[w].height = ((v - 16 + CVO) / FHeight) * FHeight;
  1624.     RSlocal[w].width = ((h - 16 + CHO) / FWidth) * FWidth;
  1625.     RSlocal[w].rheight = v - 16;
  1626.     RSlocal[w].rwidth = h - 16;
  1627.  
  1628. /*
  1629. *  Get rid of the scroll bars which were in the old size.
  1630. *  Hiding them causes the region to be updated later.
  1631. */
  1632.     if (RSlocal[w].scroll != NULL )
  1633.         HideControl(RSlocal[w].scroll);
  1634.     if (RSlocal[w].left != NULL ) 
  1635.         HideControl(RSlocal[w].left);
  1636.  
  1637.     DrawGrowIcon(RSlocal[w].window);            /* Draw in the necessary bugger */
  1638.  
  1639. /*    move the scroll bars to their new positions and sizes, and redisplay them */    
  1640.  
  1641.     if (RSlocal[w].scroll != NULL ) {
  1642.         SizeControl(RSlocal[w].scroll, 16, (v - 13));
  1643.         MoveControl(RSlocal[w].scroll, (h - 15) + CHO, -1 + CVO);
  1644.         ShowControl(RSlocal[w].scroll);
  1645.         }
  1646.     if (RSlocal[w].left != NULL ) {
  1647.         SizeControl(RSlocal[w].left, (h - 13), 16);
  1648.         MoveControl(RSlocal[w].left, -1 + CHO,  (v - 15) + CVO);
  1649.         ShowControl(RSlocal[w].left);
  1650.         }
  1651.         
  1652.     SetRect(&RSlocal[w].textrect, 0, 0, RSlocal[w].rwidth, RSlocal[w].rheight);
  1653.     
  1654. } /* RSsetsize */
  1655.  
  1656. RgnHandle RSGetTextSelRgn(short w)
  1657. {
  1658.     Rect    temp, temp2;
  1659.     Point    lb, ub;
  1660.     Point    curr;
  1661.     Point    last;
  1662.     RgnHandle    rgnH, tempRgn;
  1663.  
  1664.     rgnH = NewRgn();
  1665.     if (rgnH == nil) {
  1666.         return nil;
  1667.         }
  1668.  
  1669.     tempRgn = NewRgn();
  1670.     if (tempRgn == nil) {
  1671.         DisposeRgn(rgnH);
  1672.         return nil;
  1673.         }
  1674.  
  1675.     RSsetwind(w);
  1676.  
  1677.     curr = RSlocal[w].anchor;
  1678.     last = RSlocal[w].last;
  1679.  
  1680.   /* normalize coordinates with respect to visible area of virtual screen */
  1681.     curr.v -= RScurrent->topline;
  1682.     curr.h -= RScurrent->leftmarg;
  1683.     last.v -= RScurrent->topline;
  1684.     last.h -= RScurrent->leftmarg;
  1685.  
  1686.     if (curr.v == last.v)
  1687.       {
  1688.       /* highlighted text all on one line */
  1689.         if (curr.h < last.h) /* get bounds the right way round */
  1690.           {
  1691.             ub = curr;
  1692.             lb = last;
  1693.           }
  1694.         else
  1695.           {
  1696.             ub = last;
  1697.             lb = curr;
  1698.           } /* if */
  1699.         MYSETRECT /* set up rectangle bounding area to be highlighted */
  1700.           (
  1701.             temp,
  1702.             (ub.h + 1) * RScurrent->fwidth,
  1703.             ub.v * RScurrent->fheight,
  1704.             (lb.h + 1) * RScurrent->fwidth,
  1705.             (lb.v + 1) * RScurrent->fheight
  1706.           );
  1707.         SectRect(&temp, &noConst, &temp2); /* clip to constraint rectangle */
  1708.         RectRgn(rgnH, &temp2);
  1709.       }
  1710.     else
  1711.       {
  1712.       /* highlighting across more than one line */
  1713.         if (curr.v < last.v)
  1714.             ub = curr;
  1715.         else
  1716.             ub = last;
  1717.         if (curr.v > last.v)
  1718.             lb = curr;
  1719.         else
  1720.             lb = last;
  1721.         MYSETRECT /* bounds of first (possibly partial) line to be highlighted */
  1722.           (
  1723.             temp,
  1724.             (ub.h + 1) * RScurrent->fwidth,
  1725.             ub.v * RScurrent->fheight,
  1726.             RScurrent->width,
  1727.             (ub.v + 1) * RScurrent->fheight
  1728.           );
  1729.         SectRect(&temp, &noConst, &temp2); /* clip to constraint rectangle */
  1730.         RectRgn(rgnH, &temp2);
  1731.  
  1732.         MYSETRECT /* bounds of last (possibly partial) line to be highlighted */
  1733.           (
  1734.             temp,
  1735.             0,
  1736.             lb.v * RScurrent->fheight,
  1737.             (lb.h + 1) * RScurrent->fwidth,
  1738.             (lb.v + 1) * RScurrent->fheight
  1739.           );
  1740.         SectRect(&temp, &noConst, &temp2); /* clip to constraint rectangle */
  1741.         RectRgn(tempRgn, &temp2);
  1742.         UnionRgn(tempRgn, rgnH, rgnH);
  1743.  
  1744.         if (lb.v - ub.v > 1) /* highlight extends across more than two lines */
  1745.           {
  1746.           /* highlight complete in-between lines */
  1747.             SetRect
  1748.               (
  1749.                 &temp,
  1750.                 0,
  1751.                 (ub.v + 1) * RScurrent->fheight,
  1752.                 RScurrent->width,
  1753.                 lb.v * RScurrent->fheight
  1754.               );
  1755.             SectRect(&temp, &noConst, &temp2); /* clip to constraint rectangle */
  1756.             RectRgn(tempRgn, &temp2);
  1757.             UnionRgn(tempRgn, rgnH, rgnH);
  1758.  
  1759.           } /* if */
  1760.       } /* if */
  1761.  
  1762.     DisposeRgn(tempRgn);
  1763.     
  1764.     return rgnH;
  1765. }
  1766.  
  1767. void RSdrawsep
  1768.   (
  1769.     short w,
  1770.     short y1,
  1771.     short draw /* 1 to draw the line, 0 to erase the existing line */
  1772.   )
  1773.   /* draws a dotted line separating the screen contents from the
  1774.     scrollback area. This is currently conditionally compiled to
  1775.     be a no-op. */
  1776.   {
  1777. #ifdef SEPLINE
  1778.     RSsetwind(w);
  1779.     PenPat(gray);
  1780.     if (draw)
  1781.         PenMode(srcCopy);
  1782.     else
  1783.         PenMode(srcXor);
  1784.     MoveTo(0, y1 * RScurrent->fheight);
  1785.     Line(RSlocal[w].width-1, 0);
  1786.     PenMode(srcOr);
  1787.     RSsetattr(0);
  1788. #else
  1789.     UNUSED_ARG(w)
  1790.     UNUSED_ARG(y1)
  1791.     UNUSED_ARG(draw)
  1792. #endif SEPLINE
  1793.   } /* RSdrawsep */
  1794.  
  1795. void RSfontmetrics
  1796.   (
  1797.     void
  1798.   )
  1799.   /* calculates various metrics for drawing text with selected font
  1800.     and size in current grafport into *RScurrent. */
  1801.   {
  1802.     FontInfo finforec;
  1803.     GrafPtr myGP;
  1804.  
  1805.     GetPort(&myGP); 
  1806. #ifdef GOTTHEDOUGH
  1807.     TextFace(bold);            /* NCSA: SB */
  1808. #endif
  1809.     GetFontInfo(&finforec);
  1810.     RScurrent->fascent = finforec.ascent;
  1811.     RScurrent->fheight = finforec.ascent + finforec.descent + finforec.leading /* +1 */;
  1812.     RScurrent->monospaced = (CharWidth('W') == CharWidth('i'));   
  1813. /*    RScurrent->monospaced = (CharWidth('W') == CharWidth('i') == CharWidth(' '));  */
  1814.  
  1815. /*    if (RScurrent->monospaced)    */                        /* NCSA: SB */
  1816.         RScurrent->fwidth = CharWidth('W'); 
  1817. /*    else     
  1818.         RScurrent->fwidth = finforec.widMax; */            /* NCSA: SB */
  1819. #ifdef GOTTHEDOUGH
  1820.     TextFace(myGP->txFace - bold);        /* NCSA: SB */
  1821. #endif
  1822. }
  1823.  
  1824. void RSchangefont
  1825.   (
  1826.     short w,
  1827.     short fnum, /* new font ID or -1 for no change */
  1828.     long fsiz, /* new font size or 0 for no change */
  1829.     short resizwind /* should I resize window to keep same number of visible lines & cols */
  1830.   )
  1831.   {
  1832.     Rect pRect;
  1833.     short x1, x2, y1, y2, width, lines;
  1834.     short srw,srh;
  1835.     WStateData *wstate;
  1836.     WindowPeek wpeek;
  1837.     short resizeWidth, resizeHeight;        /* NCSA: SB */
  1838.  
  1839.     RSsetwind(w);
  1840.     srw = RScurrent->rwidth;
  1841.     srh = RScurrent->rheight;
  1842.  
  1843.     if (fnum != -1)
  1844.       {
  1845. #if 1                                /* BYU */
  1846.         RSTextFont(fnum,fsiz,0);    /* BYU */
  1847. #else
  1848.         TextFont(fnum);
  1849. #endif
  1850.         RScurrent->fnum = fnum;
  1851.       } /* if */
  1852.     if (fsiz)
  1853.       {
  1854.         TextSize(fsiz);
  1855.         RScurrent->fsiz = fsiz;
  1856.       } /* if */
  1857.     RSfontmetrics();
  1858.  
  1859.     width = VSmaxwidth(w) + 1;
  1860.     lines = VSgetlines(w);
  1861.     if (!resizwind)
  1862.       {
  1863.       /* round window size to new character cell dimensions */
  1864.         RScurrent->height =
  1865.             ((RScurrent->rheight) / RScurrent->fheight) * RScurrent->fheight;
  1866.         RScurrent->width =
  1867.             ((RScurrent->rwidth + CHO) / RScurrent->fwidth ) * RScurrent->fwidth
  1868.                 - CHO;
  1869.       }
  1870.     else
  1871.       {
  1872.       /* resize window to preserve its dimensions in character cell units */
  1873.         VSgetrgn(w, &x1, &y1, &x2, &y2);
  1874.         RScurrent->rwidth =
  1875.             RScurrent->width = (x2 - x1 + 1) * RScurrent->fwidth - CHO;
  1876.         RScurrent->rheight =
  1877.             RScurrent->height= (y2 - y1 + 1) * RScurrent->fheight;
  1878.       } /* if */
  1879.  
  1880.     if (RScurrent->rwidth > RMAXWINDOWWIDTH - 16 - CHO)
  1881.           RScurrent->rwidth = RMAXWINDOWWIDTH - 16 - CHO;
  1882.     if (RScurrent->rheight > RMAXWINDOWHEIGHT - 16)
  1883.           RScurrent->rheight = RMAXWINDOWHEIGHT - 16;
  1884.     
  1885.     RScheckmaxwind(&RScurrent->window->portRect,RScurrent->rwidth +16,    /* NCSA: SB */
  1886.         RScurrent->rheight + 16, &resizeWidth, &resizeHeight);            /* NCSA: SB */
  1887.  
  1888.  
  1889.     SizeWindow
  1890.       (
  1891.         RScurrent->window,
  1892.         RScurrent->rwidth + 16, RScurrent->rheight+16,
  1893.         FALSE
  1894.       ); /*  TRUE if done right */
  1895.     RSsetsize(w, RScurrent->rheight + 16, RScurrent->rwidth + 16);
  1896.  
  1897.     wpeek = (WindowPeek) RScurrent->window;
  1898.  
  1899.     HLock(wpeek->dataHandle);
  1900.     wstate = (WStateData *) *wpeek->dataHandle;
  1901.  
  1902.     BlockMove(&pRect, &wstate->stdState, 8);
  1903.     pRect.right = pRect.left + RMAXWINDOWWIDTH;
  1904.     if (pRect.right > TelInfo->screenRect.right)
  1905.         pRect.right = TelInfo->screenRect.right;
  1906.     pRect.bottom = pRect.top + RMAXWINDOWHEIGHT;
  1907.     BlockMove(&wstate->stdState, &pRect, 8);
  1908.  
  1909.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  1910.     VSsetrgn(w, x1, y1,
  1911.         (short) (x1 + (RScurrent->rwidth ) / RScurrent->fwidth - 1),
  1912.         (short) (y1 + (RScurrent->rheight) / RScurrent->fheight - 1));
  1913.     VSgetrgn(w, &x1, &y1, &x2, &y2);        /* Get new region */
  1914.     
  1915.     DrawGrowIcon(RScurrent->window);
  1916.     VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1); /* redraw newly-revealed area, if any */
  1917.     ValidRect(&RScurrent->window->portRect); /* no need to do it again */
  1918.     DrawControls(RScurrent->window);
  1919.   } /* RSchangefont */
  1920.  
  1921. short RSgetfont
  1922.   (
  1923.     short w, /* which window */
  1924.     short *pfnum, /* where to return font ID */
  1925.     short *pfsiz /* where to return font size */
  1926.   )
  1927.   /* returns the current font ID and size setting for the specified window. */
  1928.   {
  1929. /*
  1930. *  Bug fix.  RSsetwind's error conditions are all < 0.  There is a success condition == 1.
  1931. *  TK 12/17/88
  1932. */
  1933.     if (0 > RSsetwind(w))
  1934.         return -1;
  1935.     *pfnum = RScurrent->fnum;
  1936.     *pfsiz = RScurrent->fsiz;
  1937.     return(0);
  1938.   } /* RSgetfont */
  1939.  
  1940. short RSnewwindow
  1941.   (
  1942.     RectPtr wDims, /* window bounds in pixels */
  1943.     short scrollback, /* number of lines to save off top */
  1944.     short width, /* number of characters per text line (80 or 132) */
  1945.     short lines, /* number of text lines */
  1946.     StringPtr name, /* window name */
  1947.     short wrapon, /* autowrap on by default */
  1948.     short fnum, /* ID of font to use initially */
  1949.     short fsiz, /* size of font to use initially */
  1950.     short showit, /* window initially visible or not */
  1951.     short goaway, /* NCSA 2.5 */
  1952.     short forcesave        /* NCSA 2.5: force screen save */
  1953.   )
  1954.   /* creates a virtual screen and a window to display it in. */
  1955.   {
  1956.     GrafPort gp; /* temp port for getting text parameters */
  1957.     short w;
  1958.  
  1959.     Rect        pRect;
  1960.     short        wheight, wwidth;
  1961.     WStateData    *wstate;
  1962.     WindowPeek    wpeek;
  1963.     CTabHandle    RSctab;
  1964.  
  1965.   /* create the virtual screen */
  1966.     w = VSnewscreen(scrollback, (scrollback != 0), /* NCSA 2.5 */
  1967.         width,1, forcesave);    /* NCSA 2.5 */
  1968.     if (w < 0) {        /* problems opening the virtual screen -- tell us about it */
  1969.         return(-1);
  1970.           }
  1971.       
  1972.     RScurrent = RSlocal + w;
  1973.  
  1974.     RScurrent->fnum = fnum;
  1975.     RScurrent->fsiz = fsiz;
  1976.  
  1977.     OpenPort(&gp);
  1978. #if 1                            /* BYU */
  1979.     RSTextFont(fnum,fsiz,0);    /* BYU */
  1980. #else
  1981.     TextFont(fnum);
  1982. #endif
  1983.     TextSize(fsiz);
  1984.     RSfontmetrics();
  1985.     ClosePort(&gp);
  1986.  
  1987.     if ((wDims->right - wDims->left) > RMAXWINDOWWIDTH)
  1988.         wDims->right = wDims->left + RMAXWINDOWWIDTH;
  1989.     if ((wDims->bottom - wDims->top) > RMAXWINDOWHEIGHT)
  1990.         wDims->bottom = wDims->top + RMAXWINDOWHEIGHT;
  1991.     wwidth = wDims->right - wDims->left;
  1992.     wheight = wDims->bottom - wDims->top;
  1993.  
  1994.   /* create the window */
  1995.     if (!RScolor) {
  1996.         RScurrent->window = NewWindow(0L, wDims, name, showit?TRUE:FALSE, 8,    /* BYU LSC */
  1997.             kInFront, goaway ? TRUE:FALSE, (long)w);
  1998.         RScurrent->pal = NULL;
  1999.         if (RScurrent->window == NULL) {
  2000.             VSdetach(w);
  2001.             return(-2);
  2002.             }
  2003.         }
  2004.     else
  2005.       {
  2006.         RScurrent->window = NewCWindow(0L, wDims, name, showit?TRUE:FALSE, (short)8,    /* BYU LSC */
  2007.             kInFront, goaway ? TRUE:FALSE, (long)w);
  2008.                     /* the screen is not there until we can see it..... */
  2009.         if (RScurrent->window == NULL) {
  2010.             VSdetach(w);
  2011.             return(-2);
  2012.             }
  2013.  
  2014.         RSctab = (CTabHandle) NewHandleClear((long) (sizeof(ColorTable) + 4 * sizeof(CSpecArray)));
  2015.         if (RSctab == NULL) {
  2016.             DisposeWindow(RScurrent->window);
  2017.             VSdetach(w);
  2018.             return(-2);
  2019.             }
  2020.         HLock((Handle) RSctab);
  2021.  
  2022.         (*RSctab)->ctSize = 3;        // Number of entries minus 1
  2023.         (*RSctab)->ctFlags = 0;
  2024.         RScurrent->RGBs[0].red  =(*RSctab)->ctTable[0].rgb.red        =     0;
  2025.         RScurrent->RGBs[0].green=(*RSctab)->ctTable[0].rgb.green    =     0;
  2026.         RScurrent->RGBs[0].blue =(*RSctab)->ctTable[0].rgb.blue        =     0;
  2027.         RScurrent->RGBs[1].red  =(*RSctab)->ctTable[1].rgb.red        = 65535;
  2028.         RScurrent->RGBs[1].green=(*RSctab)->ctTable[1].rgb.green    = 65535;
  2029.         RScurrent->RGBs[1].blue =(*RSctab)->ctTable[1].rgb.blue        = 65535;
  2030.         RScurrent->RGBs[2].red  =(*RSctab)->ctTable[2].rgb.red        =     0;
  2031.         RScurrent->RGBs[2].green=(*RSctab)->ctTable[2].rgb.green    = 61183;
  2032.         RScurrent->RGBs[2].blue =(*RSctab)->ctTable[2].rgb.blue        = 11060;
  2033.         RScurrent->RGBs[3].red  =(*RSctab)->ctTable[3].rgb.red        = 61183;
  2034.         RScurrent->RGBs[3].green=(*RSctab)->ctTable[3].rgb.green    =  2079;
  2035.         RScurrent->RGBs[3].blue =(*RSctab)->ctTable[3].rgb.blue        =  4938;
  2036.         (*RSctab)->ctTable[0].value = 0;
  2037.         (*RSctab)->ctTable[1].value = 0;
  2038.         (*RSctab)->ctTable[2].value = 0;
  2039.         (*RSctab)->ctTable[3].value = 0;
  2040.         HUnlock((Handle) RSctab);
  2041.  
  2042.         RScurrent->pal = NewPalette(4, RSctab, pmCourteous, 0);
  2043.         DisposeHandle((Handle) RSctab);
  2044.         if (RScurrent->pal == NULL) {
  2045.             DisposeWindow(RScurrent->window);
  2046.             VSdetach(w);
  2047.             return(-2);
  2048.             }
  2049.  
  2050.         SetPalette(RScurrent->window, RScurrent->pal, TRUE);
  2051.       } /* if */
  2052.  
  2053.     SetPort(RScurrent->window);
  2054.     SetOrigin(CHO, CVO);            /* Cheap way to correct left margin problem */
  2055.  
  2056.     wpeek = (WindowPeek) RScurrent->window;
  2057.  
  2058.     HLock(wpeek->dataHandle);
  2059.     wstate = (WStateData *) *wpeek->dataHandle;
  2060.  
  2061.     BlockMove(&wstate->userState, wDims, 8);
  2062.     pRect.top = wDims->top;
  2063.     pRect.left = wDims->left;
  2064.     pRect.right = pRect.left + RMAXWINDOWWIDTH;
  2065.     if (pRect.right > TelInfo->screenRect.right)
  2066.         pRect.right = TelInfo->screenRect.right;
  2067.  
  2068.     pRect.bottom = pRect.top + RMAXWINDOWHEIGHT;
  2069.     BlockMove(&wstate->stdState, &pRect, 8);
  2070.  
  2071.   /* create scroll bars for window */
  2072.     pRect.top = -1 + CVO;
  2073.     pRect.bottom = wheight - 14 + CVO;
  2074.     pRect.left = wwidth - 15 + CHO;
  2075.     pRect.right = wwidth + CHO;
  2076.     RScurrent->scroll = NewControl(RScurrent->window, &pRect, "\p", FALSE,    /* BYU LSC */
  2077.         0, 0, 0, 16, 1L);
  2078.  
  2079.     if (RScurrent->scroll == 0L) return(-3);
  2080.  
  2081.     pRect.top = wheight - 15 + CVO;
  2082.     pRect.bottom = wheight + CVO;
  2083.     pRect.left = -1 + CHO;
  2084.     pRect.right = wwidth - 14 + CHO;
  2085.     RScurrent->left = NewControl(RScurrent->window, &pRect, "\p", FALSE,        /* BYU LSC */
  2086.         0, 0, 0, 16, 1L);
  2087.  
  2088.     if (RScurrent->left == 0L) return(-3);
  2089.  
  2090.     RScurrent->skip = 0; /* not skipping output initially */
  2091.     RScurrent->max = 0; /* scroll bar settings will be properly initialized by subsequent call to VSsetrgn */
  2092.     RScurrent->min = 0;
  2093.     RScurrent->current = 0;
  2094.     RScurrent->lmax = 0;
  2095.     RScurrent->lmin = 0;
  2096.     RScurrent->lcurrent = 0;
  2097.     RScurrent->selected = 0;    /* no selection initially */
  2098.     RScurrent->cursorstate = 0;    /* BYU 2.4.11 - cursor off initially */
  2099.     RScurrent->flipped = 0;        /* Initially, the color entries are not flipped */
  2100.  
  2101.     RSsetsize(w, wheight, wwidth);
  2102.     VSsetlines(w, lines);
  2103.     VSsetrgn(w, 0, 0, ((wwidth - 16 + CHO) / FWidth -1),
  2104.         ((wheight - 16 + CVO) / FHeight - 1));
  2105.  
  2106. #if 1                                                /* BYU */
  2107.     RSTextFont(RScurrent->fnum,RScurrent->fsiz,0);    /* BYU LSC */
  2108. #else
  2109.     TextFont(RScurrent->fnum);
  2110. #endif
  2111.     TextSize(RScurrent->fsiz);                /* 9 point*/
  2112.     if (!RScolor)
  2113.         TextMode(srcXor);            /* Xor mode*/
  2114.     else
  2115.         TextMode(srcCopy);
  2116.  
  2117.     if (wrapon)
  2118.       /* turn on autowrap */
  2119.         VSwrite(w, "\033[?7h",5);
  2120.  
  2121.     return(w);
  2122.   } /* RSnewwindow */
  2123.  
  2124. void RSkillwindow
  2125.   (
  2126.     short w
  2127.   )
  2128.   /* closes a terminal window. */
  2129.   {
  2130.      RSdata *temp = RSlocal + w;
  2131.  
  2132.      if (temp->pal != NULL) {
  2133.          DisposePalette(temp->pal);        
  2134.          temp->pal = NULL;
  2135.         }
  2136.  
  2137.     VSdetach(w);        /* Detach the virtual screen */
  2138.     KillControls(RSlocal[w].window);  /* Get rid of those little slidy things */
  2139.     DisposeWindow(RSlocal[w].window);    /* Get rid of the actual window */
  2140.     RSdetach(w);        /* Detach from the table */
  2141.   }
  2142.  
  2143. void RSzoom
  2144.   (
  2145.     GrafPtr window, /* window to zoom */
  2146.     short code, /* inZoomIn or inZoomOut */
  2147.     short shifted /* bring to front or not */
  2148.   )
  2149.   /* called after a click in the zoom box, to zoom a terminal window. */
  2150.   {
  2151.     WStateData    **WSDhdl;
  2152.     short        w;
  2153.     short        h, v, x1, x2, y1, y2;
  2154.     short        width, lines;            // For setting Standard State before zooming
  2155.     short        top, left;                // Ditto
  2156.     
  2157.     SetPort(window);
  2158.     w = RSfindvwind(window); /* which window is it, anyway */
  2159.  
  2160.     width = VSmaxwidth(w) + 1;
  2161.     lines = VSgetlines(w);
  2162.     WSDhdl = (WStateData **)((WindowPeek)window)->dataHandle;
  2163.     top = (**WSDhdl).userState.top;
  2164.     left = (**WSDhdl).userState.left;
  2165.     HLock((Handle)WSDhdl);
  2166.     SetRect(&((*WSDhdl)->stdState), left, top, RMAXWINDOWWIDTH + left,
  2167.                 RMAXWINDOWHEIGHT + top);
  2168.     HUnlock((Handle)WSDhdl);
  2169.     
  2170.     /* EraseRect(&window->portRect); */
  2171.     ZoomWindow(window, code, shifted);
  2172.     EraseRect(&window->portRect);            /* BYU 2.4.15 */
  2173.  
  2174.   /* get new window size */
  2175.     h = window->portRect.right - window->portRect.left;
  2176.     v = window->portRect.bottom - window->portRect.top;
  2177.  
  2178.     RSsetsize(w, v, h); /* save new size settings and update scroll bars */
  2179.   /* update the visible region of the virtual screen */
  2180.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  2181.     VSsetrgn(w, x1, y1, (x1 + (h - 16 + CHO) / FWidth -1),
  2182.         (y1 + (v - 16 + CVO) / FHeight - 1));
  2183.     VSgetrgn(w, &x1, &y1, &x2, &y2);        /* Get new region */
  2184.   /* refresh the part which has been revealed, if any */
  2185.     VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1); 
  2186.   /* window contents are now completely valid */
  2187.     ValidRect(&window->portRect);
  2188.   } /* RSzoom */
  2189.  
  2190. /*
  2191. *  This routine is called when the user presses the grow icon, or when the size of
  2192. *  the window needs to be adjusted (where==NULL, modifiers==0).
  2193. *  It limits the size of the window to a legal range.
  2194. */
  2195.  
  2196. void RSsize (GrafPtr window, long *where, long modifiers)
  2197. {
  2198.     Rect    SizRect;
  2199.     long    size;
  2200.     short    w, width, lines;
  2201.     short    tw, h, v, x1, x2, y1, y2, th;
  2202.     Boolean    changeVSSize = false;
  2203.     short    screenIndex = 0;
  2204.     Boolean    screenIndexValid = false;
  2205.  
  2206.     if ((w = RSfindvwind(window)) < 0)
  2207.         return;
  2208.     
  2209.     if (modifiers & cmdKey) return;
  2210.     
  2211.     screenIndexValid = (screenIndex = findbyVS(w)) != -1;
  2212.  
  2213.     changeVSSize = (modifiers & optionKey) == optionKey;
  2214.  
  2215. #define DONT_DEFAULT_CHANGE_VS_IF_NAWS                // JMB
  2216.     // 931112, ragge, NADA, KTH 
  2217.     // I think this is the way it should work, if there is naws available it
  2218.     // should be used by default, and option toggles behaviour.
  2219.     // Maybe it should be user configurable?
  2220. #ifndef DONT_DEFAULT_CHANGE_VS_IF_NAWS
  2221.     if(screenIndexValid && screens[screenIndex].naws) {
  2222.         changeVSSize = (modifiers & optionKey) != optionKey;
  2223.     }
  2224. #endif
  2225.  
  2226.     SetPort(window);
  2227.  
  2228.     width = VSmaxwidth(w) + 1;
  2229.     lines = VSgetlines(w);
  2230.  
  2231.  
  2232.     if (changeVSSize) {
  2233.         th = INFINITY;
  2234.         tw = INFINITY-1;
  2235.         }
  2236.     else {
  2237.         tw = RMAXWINDOWWIDTH;
  2238.         th = RMAXWINDOWHEIGHT + 1;
  2239.         }
  2240.  
  2241.     SetRect(&SizRect, 48, 48, tw + 1, th);
  2242.     
  2243.     if (where)                                            /* grow icon actions */
  2244.         {                            
  2245.         if (changeVSSize) { /* 931112, ragge, NADA, KTH */
  2246.             setupForGrow(window, 1 - CHO, 1 - CVO, FWidth, FHeight);
  2247.         }
  2248.         size = GrowWindow(window, *(Point *) where, &SizRect);    /* BYU LSC */
  2249.         if (changeVSSize) { /* 931112, ragge, NADA, KTH */
  2250.             cleanupForGrow(window);
  2251.         }
  2252.  
  2253.         if (size != 0L)
  2254.           {
  2255.             SizeWindow(window, size & 0xffff, (size >> 16) & 0xffff, FALSE);
  2256.             h = window->portRect.right - window->portRect.left;
  2257.             v = window->portRect.bottom - window->portRect.top;
  2258.           }
  2259.         else return;                            /* user skipped growing */
  2260.       }
  2261.     else
  2262.       {                                    /* just resize the window */
  2263.         h = window->portRect.right - window->portRect.left;    /* same width */
  2264.         v = (FHeight) * (VSgetlines(w));                    /* new height */
  2265.         SizeWindow(window, h, v, FALSE);                    /* change it */
  2266.         }     
  2267.  
  2268.     RSsetsize(w, v, h); /* save new size settings and update scroll bars */
  2269.  
  2270.     
  2271.   /* update the visible region of the virtual screen */
  2272.  
  2273.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  2274.     VSsetrgn(w, x1, y1, (short)((x1 + (h - 16 + CHO) / FWidth - 1)),
  2275.         (short)((y1 + (v - 16) / FHeight - 1)));
  2276.     VSgetrgn(w, &x1, &y1, &x2, &y2);        /* Get new region */
  2277.  
  2278.     if (changeVSSize) {
  2279.         
  2280.         VSsetlines(w,y2 -y1 +1);
  2281.         RScalcwsize(w,x2 - x1 +1);
  2282.         if (screenIndexValid && screens[screenIndex].naws)
  2283.             SendNAWSinfo(&screens[screenIndex], (x2-x1+1), (y2-y1+1));
  2284.         return;
  2285.         }
  2286.  
  2287.     VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1);        /* refresh the part which has been revealed, if any */
  2288.     ValidRect(&window->portRect);                        /* window contents are now completely valid */
  2289.   } /* RSsize */
  2290.  
  2291.  
  2292.  
  2293. SIMPLE_UPP(ScrollProc,ControlAction);
  2294. pascal void ScrollProc(ControlHandle control, short part)
  2295.   /* scroll-tracking routine which does continuous scrolling of visible
  2296.      region. */
  2297.   {
  2298.     short w, kind, x1, y2, x2, y1;
  2299.  
  2300.     kind = RSfindscroll(control, &w);
  2301.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  2302.  
  2303.     if (kind == 2)
  2304.       { /* horizontal scroll bar */
  2305.         switch (part)
  2306.           {
  2307.             case inUpButton:                            /* Up is left */
  2308.                 VSscrolleft(w, 1);
  2309.                 break;
  2310.             case inDownButton:                            /* Down is right */
  2311.                 VSscrolright(w, 1);
  2312.                 break;
  2313.             case inPageUp:
  2314.                 VSscrolleft(w, x2 - x1); /* scroll a whole windowful */
  2315.                 break;
  2316.             case inPageDown:
  2317.                 VSscrolright(w, x2 - x1); /* scroll a whole windowful */
  2318.                 break;
  2319.             default:
  2320.                 break;
  2321.           } /* switch */
  2322.       }
  2323.     else if (kind == 1)
  2324.       { /* vertical scroll bar */
  2325.         switch (part)
  2326.           {
  2327.             case inUpButton:
  2328.                 VSscrolback(w, 1);
  2329.                 break;
  2330.             case inDownButton:
  2331.                 VSscrolforward(w, 1);
  2332.                 break;
  2333.             case inPageUp:
  2334.                 VSscrolback(w, y2 - y1); /* scroll a whole windowful */
  2335.                 break;
  2336.             case inPageDown:
  2337.                 VSscrolforward(w, y2 - y1); /* scroll a whole windowful */
  2338.                 break;
  2339.             default:
  2340.                 break;
  2341.           } /* switch */
  2342.       } /* if */
  2343.   } /* ScrollProc */
  2344.  
  2345. /* handles a click in a terminal window. */
  2346. short RSclick( GrafPtr window, EventRecord theEvent)
  2347. {
  2348.     ControlHandle ctrlh;
  2349.     short w, part, part2, x1, x2, y1, y2;
  2350.     Point    where = theEvent.where;
  2351.     short    shifted = (theEvent.modifiers & shiftKey);
  2352.     short    optioned = (theEvent.modifiers & optionKey);
  2353.  
  2354.     w = RSfindvwind(window);
  2355.     if (w < 0)
  2356.         return -1; /* what the heck is going on here?? */
  2357.     SetPort(window);
  2358.     GlobalToLocal((Point *) &where);
  2359.     part = FindControl(where, window, &ctrlh);        /* BYU LSC */
  2360.     if (part != 0)
  2361.         switch (part)
  2362.           {
  2363.             case inThumb:
  2364.                 part2 = TrackControl(ctrlh, where, 0L);        /* BYU LSC */
  2365.                 if (part2 == inThumb)
  2366.                   {
  2367.                     part = GetCtlValue(ctrlh);
  2368.                     if (ctrlh == RSlocal[w].scroll)
  2369.                       {
  2370.                       /* scroll visible region vertically */
  2371.                         VSgetrgn(w, &x1, &y1, &x2, &y2);
  2372.                         VSsetrgn(w, x1, part, x2, part + (y2 - y1));
  2373.                       }
  2374.                     else
  2375.                       { /* ctrlh must be .left */
  2376.                       /* scroll visible region horizontally */
  2377.                         VSgetrgn(w, &x1, &y1, &x2, &y2);
  2378.                         VSsetrgn(w, part, y1, part + (x2 - x1), y2);
  2379.                       } /* if */
  2380.                   } /* if */
  2381.                 break;
  2382.             case inUpButton:
  2383.             case inDownButton:
  2384.             case inPageUp:
  2385.             case inPageDown:
  2386.                 part2 = TrackControl(ctrlh, where, ScrollProcUPP);    /* BYU LSC */
  2387.     /*            InvalRect(&(**RSlocal->scroll).contrlRect); */  /* cheap fix */
  2388.                 break;
  2389.             default:
  2390.                 break;
  2391.           } /* switch */
  2392.     else
  2393.       {
  2394.         if (optioned) 
  2395.           {
  2396.           /* send host the appropriate sequences to move the cursor
  2397.             to the specified position */
  2398.             Point x;
  2399.             x = normalize(where, w);
  2400.             VSpossend(w, x.h, x.v, screens[scrn].echo); /* MAT--we can check here if we want to use normal */
  2401.                                                         /* MAT--or EMACS movement. */
  2402.           }
  2403.         else if (ClickInContent(where,w)) {            /* NCSA: SB - prevent BUS error */
  2404.             Boolean    dragged;
  2405.  
  2406.             (void) DragText(&theEvent, where, w, &dragged);
  2407.             if (!dragged) {
  2408.                 RSselect(w, where, theEvent);
  2409.                 }
  2410.             }
  2411.       } /* if */
  2412.     return
  2413.         0;
  2414.   } /* RSclick */
  2415.  
  2416. void    RShide( short w)        /* hides a terminal window. */
  2417. {
  2418.     if (RSsetwind(w) < 0)
  2419.         return;
  2420.     
  2421.     HideWindow(RScurrent->window);
  2422. }
  2423.  
  2424. void    RSshow( short w)        /* reveals a hidden terminal window. */
  2425. {
  2426.     if (RSsetwind(w) < 0)
  2427.         return;
  2428.     
  2429.     ShowWindow(RScurrent->window);
  2430. }
  2431.  
  2432.  
  2433. #ifdef NCSA_TELNET
  2434.  
  2435. extern short    NumberOfColorBoxes;
  2436. extern short    BoxColorItems[8];
  2437. extern RGBColor    BoxColorData[8];
  2438.  
  2439. void    RScprompt(short w)
  2440.   /* puts up the dialog that lets the user examine and change the color
  2441.     settings for the specified window. */
  2442. {
  2443.     short        scratchshort, ditem;
  2444.     Point        ColorBoxPoint;
  2445.     DialogPtr    dptr;
  2446.     Boolean        UserLikesNewColor;
  2447.     RGBColor    scratchRGBcolor;
  2448.     
  2449.     dptr = GetNewMySmallDialog(ColorDLOG, NULL, kInFront, (void *)ThirdCenterDialog);
  2450.  
  2451.     for (scratchshort = 0, NumberOfColorBoxes = 4; scratchshort < NumberOfColorBoxes; scratchshort++) {
  2452.         BoxColorItems[scratchshort] = ColorNF + scratchshort;
  2453.         BlockMove(&(RSlocal[w].RGBs[scratchshort]),
  2454.             &BoxColorData[scratchshort], sizeof(RGBColor));
  2455.         UItemAssign( dptr, ColorNF + scratchshort, ColorBoxItemProcUPP);
  2456.         }
  2457.         
  2458.     ColorBoxPoint.h = 0;            // Have the color picker center the box on the main
  2459.     ColorBoxPoint.v = 0;            // screen
  2460.     
  2461.     ditem = 3;    
  2462.     while (ditem > 2) {
  2463.         ModalDialog(ColorBoxModalProcUPP, &ditem);
  2464.         switch (ditem) {
  2465.             case    ColorNF:    
  2466.             case    ColorNB:    
  2467.             case    ColorBF:    
  2468.             case    ColorBB:    
  2469.                 if (theWorld.hasColorQD) {
  2470.                     UserLikesNewColor = GetColor(ColorBoxPoint, "\pPlease Select New Color",
  2471.                          &BoxColorData[ditem-ColorNF], &scratchRGBcolor);
  2472.                     if (UserLikesNewColor)
  2473.                         BoxColorData[ditem-ColorNF] = scratchRGBcolor;
  2474.                     }
  2475.                 break;
  2476.                 
  2477.             default:
  2478.                 break;
  2479.             
  2480.             } // switch
  2481.         } // while
  2482.  
  2483.     if (ditem == DLOGCancel) {
  2484.         DisposeDialog(dptr);
  2485.         return;
  2486.         }
  2487.         
  2488.     for (scratchshort = 0; scratchshort < NumberOfColorBoxes; scratchshort++) {
  2489.             BlockMove(&BoxColorData[scratchshort], 
  2490.                 &(RSlocal[w].RGBs[scratchshort]), sizeof(RGBColor));
  2491.         }
  2492.     
  2493.     /* force redrawing of entire window contents */
  2494.     SetPort(RSlocal[w].window);
  2495.     InvalRect(&RSlocal[w].window->portRect);
  2496.  
  2497.     for (scratchshort = 0; scratchshort < 6; scratchshort++)
  2498.         SetEntryColor(RSlocal[w].pal, scratchshort, &RSlocal[w].RGBs[scratchshort]);
  2499.  
  2500.     DisposeDialog(dptr);
  2501. } /* RScprompt */
  2502.  
  2503. short RSsetcolor
  2504.   (
  2505.     short w, /* window number */
  2506.     short n, /* color entry number */
  2507.     unsigned short r, /* components of new color */
  2508.     unsigned short g,
  2509.     unsigned short b
  2510.   )
  2511.   /* sets a new value for the specified color entry of a terminal window. */
  2512.   {
  2513.     if ( !theWorld.hasColorQD || (RSsetwind(w) < 0))        /* BYU */
  2514.         return(-1);
  2515.     RScurrent->RGBs[n].red = r;
  2516.     RScurrent->RGBs[n].green = g;
  2517.     RScurrent->RGBs[n].blue = b;
  2518.     if (RScolor)
  2519.       {
  2520.       /* only take account of the color settings on a color-capable machine */
  2521.         SetEntryColor(RScurrent->pal, n, &RScurrent->RGBs[n]);
  2522.         SetPort(RScurrent->window);
  2523.         InvalRect(&RScurrent->window->portRect);
  2524.       } /* if */
  2525.     return(0);
  2526.   } /* RSsetcolor */
  2527.  
  2528. Boolean NewRSsetcolor
  2529.     (
  2530.     short w, /* window number */
  2531.     short n, /* color entry number */
  2532.     RGBColor    Color
  2533.     )
  2534.   /* sets a new value for the specified color entry of a terminal window. */
  2535.   {
  2536.     if ( !theWorld.hasColorQD || (RSsetwind(w) < 0) || (n > 5) || (n < 0))
  2537.         return(-1);
  2538.     RScurrent->RGBs[n] = Color;
  2539.  
  2540.     if (RScolor) {
  2541.       /* only take account of the color settings on a color-capable machine */
  2542.         SetEntryColor(RScurrent->pal, n, &RScurrent->RGBs[n]);
  2543.         SetPort(RScurrent->window);
  2544.         InvalRect(&RScurrent->window->portRect);
  2545.       } /* if */
  2546.     return(0);
  2547.   } /* RSsetcolor */
  2548.  
  2549. void RSgetcolor
  2550.   (
  2551.     short w, /* window number */
  2552.     short n, /* color entry number */
  2553.     unsigned short *r, /* where to return components of color */
  2554.     unsigned short *g,
  2555.     unsigned short *b
  2556.   )
  2557.   /* gets the current value for the specified color entry of a terminal window. */
  2558.   {
  2559.     *r = RSlocal[w].RGBs[n].red;
  2560.     *g = RSlocal[w].RGBs[n].green;
  2561.     *b = RSlocal[w].RGBs[n].blue;
  2562.   } /* RSgetcolor */
  2563.  
  2564. short RSmouseintext                /* Point is in global coords */
  2565.   (
  2566.     short w,
  2567.     Point myPoint
  2568.   )
  2569.   /* is myPoint within the text-display area of the specified window. */
  2570.   {
  2571.     return
  2572.         PtInRect(myPoint, &RSlocal[w].textrect);     /* BYU LSC */
  2573.   } /* RSmouseintext */
  2574.  
  2575. void RSskip
  2576.   (
  2577.     short w,
  2578.     Boolean on
  2579.   )
  2580.   /* sets the "skip" flag for the specified window (whether ignore
  2581.     screen updates until further notice). */
  2582.   {
  2583.     RSlocal[w].skip = on;
  2584.   } /* RSskip */
  2585.  
  2586. /**********************************************************************************/
  2587. /*  Make sure at least this much memory is available before allocating more memory
  2588. *   for me.  Returns true or false whether that much is available.
  2589. */
  2590. short RSokmem
  2591.   (
  2592.     short amount
  2593.   )
  2594.   {
  2595.     char *p;
  2596.     
  2597.     if (NULL == (p = NewPtr(amount)))
  2598.         return(0);
  2599.     DisposPtr(p);
  2600.     return(1);
  2601.   } /* RSokmem */
  2602.  
  2603. /*------------------------------------------------------------------------------*/
  2604. /* NCSA: SB - RScalcwsize                                                         */
  2605. /*         This routine is used to switch between 80 and 132 column mode. All that    */    
  2606. /*         is passed in is the RS window, and the new width.  This calculates the    */    
  2607. /*         new window width, resizes the window, and updates everything.  - SMB    */
  2608. /*------------------------------------------------------------------------------*/
  2609. void RScalcwsize(short w, short width)
  2610. {
  2611.     short x1,x2,y1,y2;
  2612.     short lines;
  2613.     
  2614.     RSsetwind(w);
  2615.     VSsetcols(w,(short)(width-1));
  2616.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  2617.     x2= width-1;
  2618.     
  2619.     lines = VSgetlines(w);                /* NCSA: SB - trust me, you need this... */
  2620.     RScurrent->rwidth =
  2621.         RScurrent->width = (x2 - x1 + 1) * RScurrent->fwidth - CHO;
  2622.     RScurrent->rheight =
  2623.         RScurrent->height= (y2 - y1 + 1) * RScurrent->fheight; 
  2624.  
  2625.  
  2626.     if (RScurrent->rwidth > RMAXWINDOWWIDTH - 16 - CHO)
  2627.           RScurrent->rwidth = RMAXWINDOWWIDTH - 16 - CHO;
  2628.     if (RScurrent->rheight > RMAXWINDOWHEIGHT - 16)
  2629.           RScurrent->rheight = RMAXWINDOWHEIGHT - 16;
  2630.     
  2631.     SizeWindow
  2632.       (
  2633.         RScurrent->window,
  2634.         RScurrent->rwidth + 16, RScurrent->rheight+16,
  2635.         FALSE
  2636.       ); 
  2637.     RSsetsize(w, RScurrent->rheight + 16, RScurrent->rwidth + 16);
  2638.     VSgetrgn(w, &x1, &y1, &x2, &y2);
  2639.     VSsetrgn(w, x1, y1,
  2640.         (short) (x1 + (RScurrent->rwidth ) / RScurrent->fwidth - 1),
  2641.         (short) (y1 + (RScurrent->rheight) / RScurrent->fheight - 1));
  2642.     VSgetrgn(w, &x1, &y1, &x2, &y2);        /* Get new region */
  2643.     
  2644.     DrawGrowIcon(RScurrent->window);
  2645.     VSredraw(w, 0, 0, x2 - x1 + 1, y2 - y1 + 1); /* redraw newly-revealed area, if any */
  2646.     ValidRect(&RScurrent->window->portRect); /* no need to do it again */
  2647.     DrawControls(RScurrent->window);
  2648. }
  2649.  
  2650.  
  2651. /*--------------------------------------------------------------------------*/
  2652. /* NCSA: SB - RSbackground                                                    */
  2653. /*    This procedure allows Telnet to switch from dark background to light    */
  2654. /*    background.  Save the current state into the RSdata struct, so that        */
  2655. /*     we know our background state next time we want to do anything.            */
  2656. /*    Make sure the screen contents (and palette) is updated NOW.                */
  2657. /*--------------------------------------------------------------------------*/
  2658. void RSbackground(short w, short value)
  2659. {
  2660.     RGBColor temp;
  2661.     short x;
  2662.     
  2663.     RSsetwind(w);
  2664.     if ((value && !RSlocal[w].flipped) || (!value && RSlocal[w].flipped))
  2665.         {    
  2666.         RSlocal[w].flipped = !RSlocal[w].flipped;
  2667.  
  2668.         temp = RSlocal[w].RGBs[0];
  2669.         RSlocal[w].RGBs[0] = RSlocal[w].RGBs[1];
  2670.         RSlocal[w].RGBs[1] = temp;
  2671.         
  2672.         SetPort(RSlocal[w].window);
  2673.         InvalRect(&RSlocal[w].window->portRect);
  2674.     
  2675.         for (x = 0; x < 4; x++)
  2676.             SetEntryColor(RSlocal[w].pal, x, &RSlocal[w].RGBs[x]);
  2677.         }
  2678. }
  2679.  
  2680. void RScheckmaxwind(Rect *origRect,short origW, 
  2681.             short origH, short *endW, short *endH)
  2682. {
  2683.     *endW = origW;
  2684.     *endH = origH;
  2685.     
  2686.     if (origW > (TelInfo->screenRect.right - origRect->left -15 ))
  2687.         *endW = TelInfo->screenRect.right - origRect->left -15;
  2688.  
  2689.     if (origH > (TelInfo->screenRect.bottom - origRect->top -15 ))
  2690.         *endH = TelInfo->screenRect.bottom - origRect->top -15;
  2691. }        
  2692.  
  2693.  
  2694. /*--------------------------------------------------------------------------*/
  2695. /* NCSA: SB - ClickInContent                                                */
  2696. /*    This procedure is a quick check to see if the mouse click is in the        */
  2697. /*    content region of the window.  Normalize the point to be a VS location    */
  2698. /*     and then see if that is larger than what it should be...                */
  2699. /*    Used by RSClick to see if the click is in the scroll bars, or content..    */
  2700. /*--------------------------------------------------------------------------*/
  2701. short ClickInContent(Point where,short w)                /* NCSA: SB */
  2702. {                                                        /* NCSA: SB */
  2703.     Point x;                                            /* NCSA: SB */
  2704.     x = normalize(where, w);                            /* NCSA: SB */
  2705.     if (x.v >= VSgetlines(w)) return 0;                    /* NCSA: SB */
  2706.     else return 1;                                        /* NCSA: SB */
  2707. }                                                        /* NCSA: SB */
  2708.  
  2709. #endif NCSA_TELNET
  2710.